【问题标题】:Why is the copy constructor not called when the function returns? [duplicate]为什么函数返回时不调用复制构造函数? [复制]
【发布时间】:2013-12-08 10:34:50
【问题描述】:
Line Line::operator =(Line ln) {
        cout << "Assignment operator\n";
        Line temp;
        temp.ptr = new int;
        *temp.ptr = *(ln.ptr);
        return temp;
    }

在上面这段代码中,执行以下语句时没有调用复制构造函数:

return temp;

既然是按值返回,为什么不调用拷贝构造函数?

谢谢

【问题讨论】:

  • 您的运算符实现错误:operator= 应该返回一个 reference*this,而不是一个新对象。
  • @Konrad:感谢您指出这一点。所以你的意思是:*this.ptr = *(ln.ptr);并返回 *this?
  • 是的。整个temp 对象是不必要的。但是,您也不应该在这里使用(原始)指针。 C++ 提供了更好的机制。
  • @KonradRudolph:谢谢!我只是用这段代码向自己展示一些概念

标签: c++ copy-constructor


【解决方案1】:

这称为复制省略:当按值返回本地对象时,允许进行复制,而不是本地对象(您的temp)直接在调用者中构造。即使复制构造函数有副作用,这也是允许的。

【讨论】:

    【解决方案2】:

    通过上述设置,编译器很可能会省略复制构造函数,而是直接在预期返回值的位置构造临时的temp。即使复制构造函数有副作用,也明确允许复制省略。然而,即使复制被省略,复制或移动构造函数仍然必须是可访问的,即复制省略的可能性并没有放松相应构造函数的可访问规则。

    如果你觉得你绝对想要调用一个复制构造函数,你可以强制复制构造,例如,通过一个标识函数传递结果:

    template <typename T>
    T const& identity(T const& object) {
        return object;
    }
    // ...
        return identity(temp);
    

    不过,通常情况下,您会希望省略复制构造函数。

    【讨论】:

    • 该功能如何强制复制?不就是简单的内联然后as-if规则生效吗?
    • @KonradRudolph:不。语义不同,仅在非常特定的情况下才允许复制省略(有关详细信息,请参见 12.8 [class.copy] 第 31 段):“......在具有类返回类型的函数的返回语句中,当表达式是非易失性自动对象的名称..."
    • @KonradRudolph:复制省略是对“as-if”规则的豁免。使用修改后的代码,您不会返回局部变量,因此不再允许豁免。
    【解决方案3】:

    我想在前面的帖子中附加一个注释,即在构建目标对象时甚至省略了复制构造函数,它仍然必须是可访问和定义的。例如,如果您在编译器发出错误时将您的复制构造函数声明为私有(除了 MS VC++ 至少 2010 有错误:))

    【讨论】:

      猜你喜欢
      • 2021-01-04
      • 2019-11-07
      • 2021-05-14
      • 2021-02-18
      • 2014-01-14
      • 1970-01-01
      • 2012-02-28
      • 1970-01-01
      相关资源
      最近更新 更多