C++0x中的T operator+(const T&,T&&)模式,仍然需要使用move吗?

7

前段时间我被告知,实现二元运算符的通常模式需要在返回值中添加最后一个move

Matrix operator+(const Matrix &a, Matrix &&b) {
    b += a;
    return std::move(b);
}

现在有一项特殊规则: 在return中,编译器可以把返回值当做临时变量处理,这样就不需要额外的步骤了——一个简单的return b就足够了。

但是,b在这个函数中有一个名称,因此它是一个LValue——这妨碍了编译器将其视为临时变量,所以move是必需的。

在最近的C++0x标准版本中,这种情况仍然存在吗?我们是否需要使用move来实现上述模式?


2
根据这个答案std::move是不必要的。 - fredoverflow
2
尽管参数是 Matrix&& 而不是 Matrix 可能会有所不同... - fredoverflow
2
确实很复杂,是的。我认为你是对的。如果像“Matrix”这样是一个“值参数”,那么你就有了一个仅属于自己的原始副本-一个临时的。编译器知道你可以从中获取。但如果是“Matrix&&”,我不太确定。 - towi
2个回答

7
在这个例子中,您需要显式使用std::move,因为b不是非易失性自动对象的名称。 参考12.8 [class.copy] / p31 / b1:
  • 在具有类返回类型的函数中的返回语句中,当表达式是非易失性自动对象(而不是函数或catch子句参数)的名称,并且该对象与函数返回类型具有相同的cv-未限定类型时,可以通过直接将自动对象构造到函数的返回值中来省略复制/移动操作

2
啊,引用不是对象。我认为你应该强调“对象”而不是“自动”(或两者都要)。 - fredoverflow
我认为“自动”是这里的正确术语,因为它大致(或准确)翻译为“局部变量”。 - towi

0
我不确定为什么这个函数返回值方式是通过值传递的。这个函数是否应该像下面一样返回一个Matrix&&呢?
Matrix&& operator+(const Matrix &a, Matrix &&b) {
  b += a;
  return std::move(b);
}

这样做的额外优势是,x1 + x2 + x3 + ... + xn 最多只创建一个临时变量,如果 Matrix 恰好被堆栈分配(因为它从移动中获得了什么),这一点非常重要。

我认为签名应该像以下这样:

Matrix&& operator+(Matrix &&a,      Matrix &&b     );
Matrix&& operator+(const Matrix &a, Matrix &&b     );
Matrix&& operator+(Matrix &&a,      const Matrix &b);
Matrix   operator+(const Matrix &a, const Matrix &b);

不,你不应该返回 &&。这意味着你返回一个参数的引用,而你无法控制它来自哪里(“不要捡街上的东西”)。如果你返回一个 Matrix,你可以直接在其中一个参数中移动内容,并以完美的性能实现相同的效果。此外,你不需要在 (&&, &&) 上进行重载:你在那里编写的代码与 (&,&&)(&&,&&) 中的代码相同。如果你避免使用 (&&,&&) 重载,编译器将选择其中一个。你只需要三个重载。 - towi
towi:返回一个参数的引用有什么问题吗?我认为只有返回临时变量的引用才是个问题。 - Clinton
1
@towi:另外,你有什么证据表明(&&, &&)重载是不必要的吗?我认为http://ideone.com/qf3Rn表明它是必要的。 - Clinton
你是对的,我认为。如果没有重载(当然有很多需要这样做的地方),&&可以绑定到&参数。但是我错过了一个细节,如果你为你/我们的示例提供了重载(&,&&)(&&,&),编译器无法决定哪个更好。但是,如果有一个“更好”的解决方案,而不是在这里添加一个重载来“消除混乱”,那就太好了。请随意在此处进行编辑http://ideone.com/9ZhO3 - towi
不,你也可以通过从参数返回引用来创建问题。考虑(模除一些constValue& get(map<Key,Value> &d, Value &dfault) { if(not-found) return dfault;}。然后使用它与Value &v = get(..., Value{}); cout << v;,你的程序将崩溃,因为v是你为dfault创建的temp的引用。而这将在;处消失。当你cout << v时,它就消失了。 - towi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接