2013-10-25 134 views
0

我在理解C++複製構造函數時遇到了一些問題,希望有人能幫助我。複製構造函數 - 理解問題

據我所知,當一個函數返回一個類的實例時,複製構造函數被調用(除其他外)。

#include <iostream> 
using namespace std; 

class Test 
{ 
    int a; 
public: 
    Test(int a) : a(42) 
    {} 

    // Copy constructor 
    Test(const Test& other) 
    { 
     cout << "copy constructor" << endl; 
    } 
}; 

Test test_function() 
{ 
    Test a(3); 
    return a; 
} 

int main() 
{ 
    test_function(); 
    return 0; 
} 

因此,如果我執行此代碼,複製構造函數永遠不會被調用?爲什麼?哪個對象比返回?

而且,如果我更換線

test_function(); 

Test b = test_function(); 

拷貝構造函數既不是所謂的 - 爲什麼不呢?

在此先感謝

編輯: 當改變功能:

Test test_function() 
{ 
    Test a(3); 
    Test b(34); 

    if (4 < 2) 
     return a; 

    else 
     return b; 
} 

可以看到拷貝構造函數的調用,因爲編譯器不能使用靜脈阻塞。

+1

這是一個名爲「命名返回值優化」(簡稱NRVO)的優化。 –

+0

在這個例子中有一個單獨的Test對象,爲了看到copyconstructors的行爲,你至少需要2個對象。像測試b = test_function() –

+1

編譯器正確地觀察到您不使用返回的值(在任何情況下)都會優化副本。複製elision是唯一可以改變程序可觀察行爲的優化。 – jrok

回答

0

它(拷貝/移動)構造省音作爲一種優化,以避免不必要的複製/移動。另一個優化可以被應用完全忽略返回任何東西,因爲你根本沒有使用返回的值。

無論如何,你可以禁用這個優化,看你想通過這個編譯器開關消息(GCC):

-fno-elide-constructors 

但是,使用上面開關僅供測試,讓優化適用於真正的程序。

0
Test test_function() 
{ 
    Test a(3); 
    return a; 
} 

此函數聲明本地副本Test並返回它。編譯器會看到,意識到它將在創建新副本時銷燬本地副本,並簡單地將本地副本隱藏到結果中。要看到你想要的結果,這可能會更好地工作:

Test test_function(const Test& t) 
{ 
    return t; 
} 

int main() 
{ 
    Test t1; 
    Test t2 = test_function(t1); 
    return 0; 
}