2010-02-24 158 views
3

可能重複:
Why copy constructor is not called in this case?複製構造函數?

當你路過值的對象,函數或通過值的函數返回一個對象,拷貝構造函數必須被調用。但是,在一些編譯器中,這不會發生?任何解釋?

+0

什麼與鏈接? – JonH 2010-02-24 20:51:45

+0

確實。標記爲垃圾郵件。 – 2010-02-24 20:52:51

+0

我沒有看到任何垃圾郵件? – JohnJohn 2010-02-24 20:55:58

回答

5

我以爲他們指的返回值優化在許多編譯器在代碼中實現:

CThing DoSomething(); 

被變成

void DoSomething(CThing& thing); 

與事正在堆棧上聲明並傳遞到DoSomething:

CThing thing; 
DoSomething(thing); 

它可以防止需要複製CThing。

+0

它甚至比這更好。編譯器可以直接在'DoSomething'的return語句中構造'CThing',從而完全避免了開銷。 – 2010-02-24 21:26:11

5

它通常不會發生,因爲它不需要發生。這被稱爲複製elision。在許多情況下,函數不需要進行復制,因此編譯器會優化它們。例如,具有以下功能:

big_type foo(big_type bar) 
{ 
    return bar + 1; 
} 

big_type a = foo(b); 

會得到轉換爲類似:

void foo(const big_type& bar, big_type& out) 
{ 
    out = bar + 1; 
} 

big_type a; 
foo(b, a); 

去除的返回值被稱爲「返回值優化」(RVO),並實現大多數編譯器甚至在優化關閉的情況下也是如此!

+1

這不完全正確。在你的第一個代碼片段中,編譯器可以直接在'return'語句中構造'a'。它沒有像第二個代碼示例所暗示的那樣構建默認'big_type'的開銷。 – 2010-02-24 21:05:15

1

編譯器可能調用複製構造函數以傳遞值或按值返回,但它不必。該標準允許優化它(在標準中稱爲copy elision),實際上許多編譯器會這樣做,即使您沒有優化打開。解釋非常詳細,所以我會告訴你C++ FAQ LITE

短版:

struct Foo 
{ 
    int a, b; 
    Foo(int A, int B) : a(A), b(B) {} 
}; 

Foo make_me_a_foo(int x) 
{ 
    // ...blah, blah blah... 
    return Foo(x, x+1); // (1) 
} 

Foo bar = make_me_a_foo(42); // (2) 

這裏的竅門是編譯器允許從構造線bar(2)直接在生產線(1),而不會產生構建臨時Foo對象的任何開銷。