2009-05-19 85 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

报价请参阅 “返回值优化”。