【问题标题】:Copy constructor not called when returning from overloaded + operator to overloaded = operator从重载的 + 运算符返回到重载的 = 运算符时未调用复制构造函数
【发布时间】:2014-11-16 05:41:11
【问题描述】:

考虑以下代码:

#include <iostream>
using namespace std;
class loc 
{
    int longitude, latitude;
    public:
        loc() {}
        loc(int lg, int lt) 
        {
            longitude = lg;
            latitude = lt;
        }
        loc(const loc& l)
        {
            cout << "a" << endl;
        }
        loc operator = (loc op2)
        {
            longitude = op2.longitude;
            latitude = op2.latitude;
            return *this;
        }
        loc operator+(loc op2);
};
loc loc::operator+(loc op2) {
    loc temp;
    temp.longitude = op2.longitude + longitude;
    temp.latitude = op2.latitude + latitude;
    return temp;
}
int main()
{
    loc ob1(10, 20), ob2( 5, 30);
    ob1 = ob1 + ob2;
    return 0;
}

使用命令:g++ file.cpp 编译此程序时,输出为:

a
hello

然后使用命令编译这个程序:g++ -fno-elide-constructors file.cpp,输出为:

a
a
a
hello

我的问题是:

在第一种情况下,为什么省略了两个复制构造函数?

到底哪些复制构造函数被省略了? =运算符或+运算符是否有不同的机制

编辑

我知道正确的赋值运算符或复制构造函数应该是什么样子。请回答为什么在上述情况下省略了两个复制构造函数而不是更正赋值运算符。

【问题讨论】:

  • 复制构造函数被省略,因为标准特别允许这种行为。
  • 这个类不需要自定义复制构造函数和赋值运算符。您的赋值运算符是错误的,因为它应该返回一个非常量引用。
  • @AlokSave:我在问为什么省略了两个复制构造函数。通常只会省略一个。
  • 您的赋值运算符具有未定义的行为。您没有从中返回任何内容,并且返回类型不是 void。
  • @BenjaminLindley:进行了编辑。仍然得到相同的输出。

标签: c++ operator-overloading copy-constructor return-value-optimization copy-elision


【解决方案1】:

一个省略的副本是从 op+ 返回的。 RVO 允许直接在最终目的地构造结果,完全省略temp。省略的副本来自temp

第二个省略的副本将 op+ 的结果(这是一个临时的)传递给 op=。相反,它安排 op+ 的结果直接在 op2 参数中构造。这不是 RVO,只是正常的临时省略。

【讨论】:

  • 如果这是真的,那么还应该调用两个复制构造函数——一个用于将参数按值传递给+,另一个用于将值传递给=。但是这里只调用了一个拷贝构造函数。
  • 我列出的第二个省略将值传递给 op=。 (为什么不直接看生成的代码?)
  • 根据您的回答,省略的第一个构造函数是为返回创建的临时对象,该对象直接构造到目标中(实际上是 = 您在第二段中省略的参数)。见此链接:stackoverflow.com/questions/26937270/…
  • 是的。并且这种直接构造节省了两份副本,一份用于返回,一份用于将参数传递给后续调用。
  • 如果return的构造被省略,那么它必须直接构建到目的地中,你能告诉在这种情况下目的地是什么吗? + 和 = 的参数是如何构造的?
猜你喜欢
  • 1970-01-01
  • 2014-10-12
  • 2018-11-20
  • 1970-01-01
  • 2021-01-28
  • 1970-01-01
  • 1970-01-01
  • 2015-09-27
  • 2013-03-26
相关资源
最近更新 更多