2013-01-24 18 views
3

我在C++初學者,我使用資源說,下面的語句D3 = D1 + D2;調用以下:爲什麼被稱爲該聲明D1 = D2 + D3在C++中拷貝構造函數?

  • +運算
  • 默認構造函數
  • 拷貝構造函數
  • 析構函數
  • 賦值運算符
  • 析構函數

我不明白爲什麼複製構造函數在結果時被調用正被分配給之前聲明的變量以及爲什麼調用2個構造函數。

運營商如下:

A a=b, 
when you return an object, 
when you pass an object. 

+運算符重載函數返回一個臨時object.which實際上將調用拷貝構造函數:當

date& date::operator=(const date& other) 
{ 
cout << "Date assignment op" << endl; 
    if (this!=&other){ 
     day=other.day; 
     month=other.month; 
     year=other.year; 
    } 
    return *this; 
} 

date date::operator+(const date& other) const 
{ 
    cout << "Date Operator + called" << endl; 
    date temp; 
    temp.day=day+other.day; 
    temp.month=month+other.month; 
    temp.year=year+other.year; 
    return temp; 
} 
+0

類型d3; d3 = d1 + d2。這就是爲什麼我努力去理解它。 –

+0

你的'+'運算符重載函數裏面有什麼?你可以發佈嗎? – Vijay

+2

複製構造函數用於構造'd1 + d2'的(臨時)返回值。 – Mankarse

回答

8

表達(d1 + d2)產生一個臨時對象,同時從操作者+(return temp)返回。從'temp'創建臨時文件是通過複製構造函數完成的。然後分配給d3。

+0

謝謝,那很完美。 –

+1

請注意,對於NRVO/RVO,您可能看不到對拷貝構造函數的調用。請複製省略讀了(http://stackoverflow.com/questions/2581424/how-to-check-for-c-copy-ellision) – Chubsdad

+0

@DanielTaylor有趣,我本來期望*命名值優化*的Elid來的複製建築。 – juanchopanza

0

拷貝構造函數被調用。

2

當計算D1 + D2,結果是臨時對象。爲了將一個對象分配給另一個對象,正在調用複製構造函數。

+0

措辭令人困惑。爲了將一個對象分配給另一個對象,真正要調用的是賦值操作符。 – juanchopanza

+0

在operator +中爲'return temp;'創建一個臨時對象,爲此複製構造函數被調用。這在到達分配操作員之前發生。對不起我的英語不好。 – nabroyan

0

不要依賴於

從技術上講,你的operator+temp可變進其塊有外面傳遞到一個臨時對象稍後給您operator=

換句話說,你的operator=看到作爲一個參數是不是裏面operator+temp,但它的一個副本,有長壽比+塊,讓=發生。

Howvever,如果任:

  • +具有僅僅只有一個return語句(因爲它實際上有)
  • +擁有所有return語句返回永遠只是一個相同的對象

的編譯器可以通過合併臨時局部變量和賦值中使用的臨時值來優化複製時返回,並根本不需要複製。

這是(見C++ 03或C++ 11 31年8月12日§12.8.15)組成,也發生切除的副作用很少的優化之一。

拷貝構造函數被調用與否,最終取決於對優化所需要的水平,編譯器的事實。

(感謝juanchopanza所有的澄清)。

+0

即使複製c-tor有副作用,複製elision也會發生,否?或者只允許在RVO中使用? – jrok

+0

@jrok:作爲一種優化,它只有在外部效應保持不變的情況下才會發生。如果副本具有副作用,eliding也會消除副作用,這將改變外部行爲。 –

+0

@jrok你是對的,副本elision *即使消除副作用也會發生。這是一種優化,可以*改變外部行爲。這是瞭解這一點非常重要的一個原因。關於這一點,答案是不正確的。關於單一的退貨聲明點,這也不完全正確。如果所有的返回語句都返回相同的對象,它可以工作。 – juanchopanza

1

默認情況下,return「荷蘭國際集團由值的對象從源對象將複製構造一個臨時對象,然後沿着該臨時給呼叫者傳遞。換句話說,該語句d3 = d1 + d2;基本上是這樣做的:

date implicit_temp(operator+(d1, d2)); 
d3 = implicit_temp; 

機罩下分解成以下邏輯:

// The + operator 
date temp; // The default constructor 
temp.day = d1.day + d2.day; 
temp.month = d1.month + d2.month; 
temp.year = d1.year + d2.year; 
// return temp; 
date implicit_temp(temp); // The copy constructor 
temp.~date(); // Destructor 
// Assignment operator 
d3.day = implicit_temp.day; 
d3.month = implicit_temp.month; 
d3.year = implicit_temp.year; 
implicit_temp.~date(); // Destructor 

這是相同的順序,你所看到的輸出。

如果編譯器支持視網膜靜脈阻塞(返回值優化),它能夠優化掉由return語句創建的臨時date對象,通過傳遞d3有一個隱藏的參數,以便return只需直接分配temp變量d3通過其=操作,使得代碼的行爲就好像它是這樣寫的:

void date::operator+(const date& other, date& result) const 
{ 
    date temp; 
    temp.day=day+other.day; 
    temp.month=month+other.month; 
    temp.year=year+other.year; 
    result = temp; 
} 

這將打破這一邏輯引擎蓋下:

// The + operator 
date temp; // The default constructor 
temp.day = d1.day + d2.day; 
temp.month = d1.month + d2.month; 
temp.year = d1.year + d2.year; 
// return temp; - Assignment operator 
d3.day = temp.day; 
d3.month = temp.month; 
d3.year = temp.year; 
temp.~date(); // Destructor