【问题标题】:How does copy constructor that returns value, discards the temp?返回值的复制构造函数如何丢弃临时值?
【发布时间】:2021-12-31 14:38:49
【问题描述】:

有这个代码:

#include <iostream>

class Base {
public:
    Base() = default;

    explicit Base(int val) : _var(val) {}

    Base operator=(const Base &rhs) {
        _var = rhs._var;
        return *this;
    }

    void print() const {
        std::cout << _var << std::endl;
    }

private:
    int _var;
};

int main() {
    Base b[] = {Base(10), Base(), Base(), Base()};
    (b[1] = b[2]) = b[0];
    for (Base base: b) {
        base.print();
    }
}

输出是:

10
0
0
0

但我希望

10
10
0
0

由于数组b[1] 中的第二个元素应该从b[0] 中赋值,但是赋值运算符返回的是值,而不是引用,因此会发生复制构造。但是,为什么不将b[1] 复制构造为具有_var=10

如果operator= 返回Base &amp;,输出将是我的预期

【问题讨论】:

  • 用括号指定b[1] = b[2]无论如何都会首先发生。 b[2] 中的 var 是什么?现在是 0
  • @AlexeyLarionov 然后b[1] 应该得到b[0] 的分配变量,即10
  • 不,b[1] = b[2] 在此处返回b[1] 的副本,请检查赋值运算符的返回类型(它不是引用类型)。所以b[0] 被分配给b[1] 的副本,然后被丢弃。
  • 为什么会这样? b[1] = b[2] 按值返回,因此它是分配给 b[0]b[1] 的临时副本。由于您不保存此副本,因此它只是被丢弃

标签: c++ copy-constructor rvalue


【解决方案1】:

要获得您的赋值运算符(顺便说一下,它与复制构造函数不同)所需的结果,您需要返回一个引用:

Base& operator=(const Base &rhs)

这是规范形式。

在没有引用的情况下,(b[1] = b[2]) 的结果将存储在临时文件中。 (b[1] = b[2]) = b[0]; 分配给那个临时的,它被丢弃并且对b[1] 没有影响。

【讨论】:

  • 但是你怎么能分配给临时的(ala rvalue)?那应该是不可能的,否则你可以做6 = 5之类的事情,并且两个操作数都是右值。那么为什么返回值的operator= 甚至可以编译呢?
  • C++ 不允许分配给内置的右值,但允许它用于用户定义的类型。
  • 我不明白。右值始终是右值,无论是原始类型、内置类型还是用户定义。为什么会有例外?
  • @milanHrabos • 啊,您所期待的是Base operator=(const Base &amp;rhs) &amp;&amp; {...,但由于您最后没有使用&amp;&amp; 限定它,所以您得到了两者。
猜你喜欢
  • 1970-01-01
  • 2016-10-10
  • 2016-10-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-07
  • 1970-01-01
  • 2021-05-28
相关资源
最近更新 更多