我使用以下代码片段来比较在C ++中创建对象的两种方法。
#include <iostream>
using std::cout;
using std::endl;
class Foo {
public:
Foo() : x(0) { cout << "In Foo constructor." << endl; }
~Foo() { cout << "In Foo destructor." << endl; }
Foo(const Foo&) { cout << "In Foo copy constructor." << endl; }
// Assignment operator.
Foo& operator=(const Foo&) {
cout << "In assignment operator." << endl;
return *this;
}
private:
int x;
};
int main() {
cout << "Constructing Foo 1" << endl;
Foo Foo_1;
cout << "Constructing Foo 2" << endl;
Foo Foo_2 = Foo();
return 0;
}
此代码段的输出为:
Constructing Foo 1
In Foo constructor.
Constructing Foo 2
In Foo constructor.
In Foo destructor.
In Foo destructor.
我正在使用 Visual C ++ 2010 (编译器版本16.x),我正在使用cl /EHsc /W4 test.cpp
编译代码段。在Foo_2
的构造中,我期望看到对构造函数和析构函数的额外调用,以便创建临时对象并调用赋值运算符,以便将临时对象分配给Foo_2
。有人可以向我解释为什么不是这种情况。如果我遗漏了一些非常明显的东西,请道歉。
答案 0 :(得分:4)
Foo
有两种初始化形式:
Foo f1;
Foo f2 = Foo();
使用默认构造函数直接构造f
。第二个使用默认构造函数构造一个Foo
类型的临时文件,并将该临时文件复制到f2
中。后者是你所描述的你所期望的。你是对的,除了一个额外的规则:如果这种形式的初始化是有效的(它在这里;使复制构造函数私有,看看会发生什么),编译器可以“忽略”复制构造和构造{直接{1}},就像在第一个版本中一样。这就是你所看到的。编译器不需要忽略复制构造函数,但我最近使用过的每一个都是。
答案 1 :(得分:1)
Foo Foo_2 = Foo();
与Foo Foo_2(Foo());
类似。编译器足够智能,不会调用赋值运算符。顺便说一下,你在赋值运算符中有一个错误 - 你返回对象的引用而不是复制它。
答案 2 :(得分:1)
本周的第一个&#34;大师&#34;问题只是关于你的问题http://www.gotw.ca/gotw/001.htm 特别是编译器优化的注意事项。