2009-05-19 106 views
3

如果我編譯(在G ++下)並運行下面的代碼,它將打印「Foo :: Foo(int)」。但是,在使複製構造函數和賦值運算符爲私有之後,它將無法編譯以下錯誤:「error:'Foo :: Foo(const Foo &)'是私有的」。如果它僅在運行時調用標準構造函數,它如何需要一個複製構造函數?構造函數訪問規則

#include <iostream> 

using namespace std; 

struct Foo { 
    Foo(int x) { 
     cout << __PRETTY_FUNCTION__ << endl; 
    } 


    Foo(const Foo& f) { 
     cout << __PRETTY_FUNCTION__ << endl; 
    } 

    Foo& operator=(const Foo& f) { 
     cout << __PRETTY_FUNCTION__ << endl; 
     return *this; 
    } 
}; 

int main() { 
    Foo f = Foo(3); 
} 

回答

15

拷貝構造函數用在這裏:

Foo f = Foo(3); 

這相當於:

Foo f(Foo(3)); 

其中第一組括號進行重新的拷貝構造函數的調用。你可以這樣避免這種情況:

Foo f(3); 

注意,編譯器可以選擇優化掉拷貝構造函數的調用,但拷貝構造函數仍然必須是可用的(即不是私人)。 C++標準特別允許這種優化(見第12.8/15節),而不管複製構造函數的實現如何。

+0

如果你聲稱它使用了複製構造函數,爲什麼你沒有看到它在輸出中。原始海報明確指出只有:: Foo(int)被調用。 – KIV 2009-05-19 10:39:53

2

你看到的是標準優化允許的結果,當編譯器避免創建臨時文件時。即使存在副作用(例如IO),編譯器也可以用簡單的構造替換構造和賦值。

但事實上,如果程序不合格或不符合情況,編譯器進行優化或不。這就是爲什麼

Foo f = Foo(3); 

需要複製構造函數。並且

Foo f(3); 

沒有。雖然它可能會導致相同的二進制代碼。從15年8月12日

When certain criteria are met, an implementation is allowed to omit the copy construction of a class object, even if the copy constructor and/or destructor for the object have side effects. In such cases, the implementation treats the source and target of the omitted copy operation as simply two different ways of referring to the same object, and the destruction of that object occurs at the later of the times when the two objects would have been destroyed without the optimization.111) This elision of copy operations is permitted in the following circumstances (which may be combined to eliminate multiple copies):

— in a return statement in a function with a class return type, when the expression is the name of a non-volatile automatic object with the same cv-unqualified type as the function return type, the copy operation can be omitted by constructing the automatic object directly into the function’s return value

— when a temporary class object that has not been bound to a reference (12.2) would be copied to a class object with the same cv-unqualified type, the copy operation can be omitted by constructing the temporary object directly into the target of the omitted copy

報價請參閱 「返回值優化」。