2011-09-27 88 views
2

有這樣的代碼:對象從功能和拷貝構造函數返回

#include <iostream> 

class A { 
public: 
    int a; 
    A() : a(0) { 
     std::cout << "Default constructor" << " " << this << std::endl; 
    } 
    A(int a_) : a(a_) { 
     std::cout << "Constructor with param " << a_ << " " << this << std::endl; 
    } 
    A(const A& b) { 
     a = b.a; 
     std::cout << "Copy constructor " << b.a << " to " << a << " " << &b << " -> " << this << std::endl; 
    } 
    A& operator=(const A& b) { 
     a=b.a; 
     std::cout << "Assignment operator " << b.a << " to " << a << " " << &b << " -> " << this << std::endl; 
    } 
    ~A() { 
     std::cout << "Destructor for " << a << " " << this << std::endl; 
    } 
    void show(){ 
     std::cout << "This is: " << this << std::endl; 
    } 
}; 


A fun(){ 
    A temp(3); 
    temp.show(); 
    return temp; 
} 


int main() { 
    { 
     A ob = fun(); 
     ob.show(); 
    } 
    return 0; 
} 

結果:

Constructor with param 3 0xbfee79dc 
This is: 0xbfee79dc 
This is: 0xbfee79dc 
Destructor for 3 0xbfee79dc 

目標對象OB是由函數fun()初始化。爲什麼複製構造函數沒有在那裏調用?我認爲,當函數按值返回時,將調用複製構造函數或賦值運算符。看起來函數fun()中構造的對象在執行函數後不會被銷燬。在這種情況下,拷貝構造函數如何被強制調用?

這是由g ++編譯的。

回答

4

爲什麼不在那裏調用構造函數?

RVO

如何可以拷貝構造函數被迫在這種情況下調用?

將選項傳遞給編譯器。對於海灣合作委員會,它是--no-elide-constructors選項來禁用RVO

3

這就是所謂的命名返回值優化複製省略,基本上意味着編譯器已經想通了,副本可以通過仔細放置臨時可以避免和對象在同一個內存位置。

默認情況下,會有在這段代碼的三個對象,tempfun,返回值和ob內主,以及多達兩個副本,但是通過仔細放置temp在相同的存儲單元返回的對象在fun之內並且將ob置於相同的存儲器地址中,兩個副本可以被優化掉。

我寫的關於這兩個優化與一對夫婦的照片來解釋這到底是怎麼回事: