2010-06-21 167 views
0
class X 
{ 
    int i; 
    public: 
    X(int m) : i(m) {}; 

    X(const X& x) 
    { 
    //cout "copy constructor is called\n"; 
    } 

    const X opearator++(X& a,int) 
    { 
    //cout "X++ is called\n"; 
    X b(a.i); 
    a.i++; 
    return b; 
    } 
    void f(X a) 
    { } 
}; 

int main() 
{ 
    X a(1); 
    f(a); 
    a++; 
    return 0; 
} 

這裏當調用函數'f'時,拷貝構造函數會按預期調用。在++的情況下,調用operator ++函數,但是當它返回「不調用複製構造函數」時。 爲什麼「,而從函數返回拷貝構造器是不是所謂的‘運營商+’?拷貝構造函數不被調用?

+0

您問*爲什麼在從函數'f'*返回時不調用複製構造函數。我不明白,'f()'是無效的,它不會返回任何東西。 – 2010-06-21 12:53:21

+2

請在提問時始終提供** real **代碼。由於你的代碼包含阻止編譯的錯誤,這顯然不是你真正使用的代碼。 – 2010-06-21 13:09:45

+0

@BinaryWorrier:'f()'不會返回任何東西,但'a ++'不會;) – 2010-06-21 13:11:18

回答

3

編譯器被允許的Elid調用當一個對象從一個函數返回一個拷貝構造函數。

也就是說,它是不需要實際調用複製構造函數:它可以構造要在對象需要從函數返回的任何位置返回的對象。

0

即使複製構造函數具有副作用,對ellide副本也是合法的。它被稱爲RVO(還有一個用於命名(評論:感謝)值,NRVO),並且被標準明確允許。

+2

NRVO中的N代表「有名」,而不是「新」。 – 2010-06-21 12:57:45

+0

足夠接近:P – Puppy 2010-06-21 13:23:21

2

它看起來像RVO(返回值優化)。你的編譯器發現你沒有對'b'實例做任何事情,也沒有對它的返回拷貝做任何事情,所以它從編譯後的輸出中刪除它(對象拷貝操作)。

+0

b未被刪除。沒有理由複製它。複製elision通過將源和目標對象合併到單個對象中工作。當應用NRVO時,b指的是函數返回的同一個對象。 – sellibitze 2010-06-21 13:41:24

+0

@sellibitze:抱歉代詞不精確。被刪除的'it'是對拷貝構造函數的調用。由於可能的構造函數副作用,編譯器不會完全優化'b'對象。與RVO一樣,這些副作用沒有得到幻燈片。感謝您的評論。 – 2010-06-21 14:27:14

0

那麼,你在你的代碼有幾個錯誤。如果你編譯並運行我附加的代碼,你會看到當operator ++返回時成功調用了copy構造器。

#include <iostream> 

class X { 
public: 
    X(int m) : i(m) {}; 

    X(const X& x) 
    { 
     std::cout << "Copy constructor is called\n"; 
    } 

    X 
    operator++(int) 
    { 
     std::cout << "X++ is called\n"; 

     this->i++; 
     return *this; 
    } 


private: 
    int i; 

}; 


void 
f(X a) 
{ 
} 


int 
main(void) 
{ 
    X a(1); 
    f(a); 
    a++; 
    return 0; 
}