为什么不调用复制构造函数?
class MyClass
{
public:
~MyClass() {}
MyClass():x(0), y(0){} //default constructor
MyClass(int X, int Y):x(X), y(Y){} //user-defined constructor
MyClass(const MyClass& tempObj):x(tempObj.x), y(tempObj.y){} //copy constructor
private:
int x; int y;
};
int main()
{
MyClass MyObj(MyClass(1, 2)); //user-defined constructor was called.
MyClass MyObj2(MyObj); //copy constructor was called.
}
在第一种情况下,当 MyClass(1, 2)
调用用户定义的构造函数并返回一个对象时,我期望 MyObj
调用复制构造函数。为什么它不需要为 MyClass
的第二个实例调用复制构造函数?
class MyClass
{
public:
~MyClass() {}
MyClass():x(0), y(0){} //default constructor
MyClass(int X, int Y):x(X), y(Y){} //user-defined constructor
MyClass(const MyClass& tempObj):x(tempObj.x), y(tempObj.y){} //copy constructor
private:
int x; int y;
};
int main()
{
MyClass MyObj(MyClass(1, 2)); //user-defined constructor was called.
MyClass MyObj2(MyObj); //copy constructor was called.
}
In the first case, when MyClass(1, 2)
calls the user-defined constructor and returns an object, I was expecting MyObj
to call the copy constructor. Why it doesn't need to call the copy constructor for the second instance of MyClass
?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
每当创建临时对象的唯一目的是复制并随后销毁时,编译器就可以完全删除临时对象并直接在接收者中(即直接在应该接收副本的对象中)构造结果。在你的情况下,
可以转化为
即使复制构造函数有副作用,也
。这个过程称为复制操作的省略。它在语言标准12.8/15中有描述。
Whenever a temporary object is created for the sole purpose of being copied and subsequently destroyed, the compiler is allowed to remove the temporary object entirely and construct the result directly in the recipient (i.e. directly in the object that is supposed to receive the copy). In your case
can be transformed into
even if the copy constructor has side-effects.
This process is called elision of copy operation. It is described in 12.8/15 in the language standard.
在这种情况下,复制构造函数可能会被省略。
与
MyClass MyObj = MyClass( 1, 2 );
类似。这样
的代码有一个隐式构造函数调用,将
char*
转换为std::string
。如果没有复制省略,通过赋值语法进行的“简单”字符串初始化将产生额外的深层复制。该语法与您所拥有的语法 99% 等效。
The copy constructor may be elided in such a case.
Likewise with
MyClass MyObj = MyClass( 1, 2 );
.And with
Such code has an implicit constructor call to convert the
char*
to astd::string
.Without copy elision, the "easy" string initialization by assignment syntax would incur an additional deep copy. And that syntax is 99% equivalent to what you have.
除了 Potatoswatter 和 Andrey T. 所说的之外,请注意,您可以劝说大多数编译器不要删除构造函数。 GCC 通常为您提供
-fno-elide-constructors
,而 MSVC 则提供/Od
,这应该会为您提供所需的输出。这是一些代码:在 MingW32 上使用 GCC 4.5.0 编译:
输出:
Apart from what Potatoswatter and Andrey T. has said, note that you can coax most compilers not to elide constructors. GCC typically provides you with
-fno-elide-constructors
and MSVC with/Od
which should give you the desired output. Here's some code:Compiled with GCC 4.5.0 on MingW32:
Output:
是什么让您认为它没有被调用?试试这个[编辑:更改代码以使用私有复制构造函数,因为即使使用复制构造函数被省略,也必须检查可用性]:
尝试编译此代码会导致两者都出现错误main 中的 em> 行:
从概念上讲,在这两种情况下都使用复制构造函数,并且编译器有义务检查它是否可访问。然而,在第一种情况下,编译器可以自由地忽略复制构造函数的实际使用,只要它能够使用它。
What makes you think it's not invoked? Try this [Edit: changing code to use private copy ctor, since availability has to be checked even if use of the copy ctor is elided]:
Attempting to compile this gives errors for both lines in
main
:Conceptually, the copy ctor is used in both cases, and the compiler is obliged to check that it's accessible. In the first case, however, the compiler is free to elide actual use of the copy ctor, as long as it would be able to use it.