c++ 中复制构造函数中的 const

发布于 2024-12-15 21:52:46 字数 590 浏览 2 评论 0原文

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

待天淡蓝洁白时 2024-12-22 21:52:46

这称为编译器完成的复制省略,并且这是语言规范所允许的。

请参阅此 wiki 条目:

至于为什么非 const 版本会给出编译错误,因为 < code>obj1.fun() 返回一个临时对象,该对象不能绑定到非常量引用,但它可以绑定到 const 引用,因此 const 版本可以正常编译。一旦将其设置为 const 引用,它仅用于语义检查,但编译器会优化代码,省略对复制构造函数的调用。

但是,如果使用 GCC 使用 -fno-elide-constructors 选项进行编译,则不会执行复制省略,并且将调用复制构造函数。 GCC 文档 说,

-fno-elide-构造函数

C++ 标准允许实现省略创建临时对象,该临时对象仅用于初始化相同类型的另一个对象。 指定此选项会禁用该优化,并强制 G++ 在所有情况下调用复制构造函数。

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,

-fno-elide-constructors

The C++ standard allows an implementation to omit creating a temporary which is only used to initialize another object of the same type. Specifying this option disables that optimization, and forces G++ to call the copy constructor in all cases.

为你鎻心 2024-12-22 21:52:46

编译器决定优化复制构造,因为它允许这样做,即使它通过 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.

心不设防 2024-12-22 21:52:46

临时变量是右值,不绑定到非常量引用。因此,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 the x::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.

べ繥欢鉨o。 2024-12-22 21:52:46

第一个错误是因为它尝试将复制构造函数与临时对象一起使用。

ob1.fun();  // This returns an x by value

因此,当您使用它时,会听到

x ob2=ob1.fun();       // You are passing it by value which requires a local temporary
// This is equivalent to this:
x  ob2(obj1.fun());    // So it is trying to do a copy construction.

“临时对象只能绑定到 const 引用”。因此无法编译。

修复该问题(使用临时的)后,它现在可以使用复制构造函数。但如果可以的话,编译器可以对其进行优化。它无法优化它,因为它甚至不允许在第一个版本中使用它。

The first error was because it was trying to use the copy constuctor with a temporary object.

ob1.fun();  // This returns an x by value

Thus when you use it hear

x ob2=ob1.fun();       // You are passing it by value which requires a local temporary
// This is equivalent to this:
x  ob2(obj1.fun());    // So it is trying to do a copy construction.

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.

小清晰的声音 2024-12-22 21:52:46

由于复制省略优化,您的复制构造函数调用被跳过。您不能依赖复制构造函数中的任何可观察行为,例如打印语句。如果您确实想查看其输出,请尝试禁用优化。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文