c++ 中复制构造函数中的 const
class x
{
int a;
public:
x()
{
cout<<"\n\ndefault constructor";
}
x(x& obj)
{
cout<<"\n\ncopy constructor";
}
x fun()
{
x ob;
return ob;
}
};
int main()
{
x ob1;
x ob2=ob1.fun();
return 0;
}
最初,这段代码给出了一个错误“没有匹配的函数来调用‘x::x(x)’”, 当我将复制构造函数更改为
x(const x& obj)
{
cout<<"\n\ncopy constructor";
}
输出时,将成为
默认构造函数
默认构造函数
复制构造函数仍然没有执行......为什么?
class x
{
int a;
public:
x()
{
cout<<"\n\ndefault constructor";
}
x(x& obj)
{
cout<<"\n\ncopy constructor";
}
x fun()
{
x ob;
return ob;
}
};
int main()
{
x ob1;
x ob2=ob1.fun();
return 0;
}
initially, this code gave an error " no matching function for call to ‘x::x(x)’",
when i changed the copy constructor to
x(const x& obj)
{
cout<<"\n\ncopy constructor";
}
the output becomes
default constructor
default constructor
still the copy constructor is not executing.... why?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
这称为编译器完成的复制省略,并且这是语言规范所允许的。
请参阅此 wiki 条目:
至于为什么非 const 版本会给出编译错误,因为 < code>obj1.fun() 返回一个临时对象,该对象不能绑定到非常量引用,但它可以绑定到 const 引用,因此 const 版本可以正常编译。一旦将其设置为 const 引用,它仅用于语义检查,但编译器会优化代码,省略对复制构造函数的调用。
但是,如果使用 GCC 使用
-fno-elide-constructors
选项进行编译,则不会执行复制省略,并且将调用复制构造函数。 GCC 文档 说,That is called copy-elision done by the compiler, and that is allowed by the language specification.
See this wiki entry:
As for why non-const version is giving compilation error because
obj1.fun()
return a temporary object which cannot be bound to non-const reference, but it can bind to const reference, so the const version compiles fine. Once you make it const reference, it is used only for semantic check, but the compiler optimizes the code, eliding the call to the copy-constructor.However, if you compile it with
-fno-elide-constructors
option with GCC, then the copy-elision will not be performed, and the copy-constructor will be called. The GCC doc says,编译器决定优化复制构造,因为它允许这样做,即使它通过 const 引用接受参数。
The compiler decided to optimize out the copy construction as it's allowed to do, even when it accepted the argument by const reference.
临时变量是右值,不绑定到非常量引用。因此,ob1.fun() 无法绑定到 x::x(x&) 构造函数。
但是,右值确实绑定到常量引用。
至于为什么没有输出:复制构造函数是标准中的一种特殊情况,并且允许编译器省略复制构造函数调用,即使复制构造函数有副作用。但是,该构造必须仍然有效!另一个这样的例子是,如果您显式地声明了复制构造函数——它仍然会被忽略,但您的代码将是错误的。
在 GCC 中,您可以说
-fno-elide-constructors
来恢复构造函数。Temporaries are rvalues and do not bind to non-constant references. So
ob1.fun()
cannot bind to thex::x(x&)
constructor.However, rvalues do bind to constant references.
As for why there's no output: The copy constructor is a special case in the standard, and the compiler is allowed to elide copy constructor calls, even if the copy constructor has side effects. However, the construction must still be valid! Another such example is if you declared the copy constructor
explicit
-- it'd still get elided, but your code would be erroneous.In GCC you can say
-fno-elide-constructors
to bring your constructor back.第一个错误是因为它尝试将复制构造函数与临时对象一起使用。
因此,当您使用它时,会听到
“临时对象只能绑定到 const 引用”。因此无法编译。
修复该问题(使用临时的)后,它现在可以使用复制构造函数。但如果可以的话,编译器可以对其进行优化。它无法优化它,因为它甚至不允许在第一个版本中使用它。
The first error was because it was trying to use the copy constuctor with a temporary object.
Thus when you use it hear
Temporaries can only be bound to const references. Thus it fails to compile.
After you fix that problem (with the temporary) it can now use the copy constructor. But the compiler is allowed to optimize it out if it can. It could not optimize it out because it was not even allowed to use it in the first version.
由于复制省略优化,您的复制构造函数调用被跳过。您不能依赖复制构造函数中的任何可观察行为,例如打印语句。如果您确实想查看其输出,请尝试禁用优化。
Your copy constructor call was skipped due to copy elision optimization. You cannot rely on any observable behavior in copy constructor such as print statements. If you do want to see output from it, try to disable optimizations.