移动构造函数用逗号操作抑制(Move constructor suppressed by comma

2019-06-27 21:17发布

这个程序:

#include <iostream>
struct T {
    T() {}
    T(const T &) { std::cout << "copy constructor "; }
    T(T &&) { std::cout << "move constructor "; }
};
int main() {
    ([](T t) -> T { return t; })({}); std::cout << '\n';
    ([](T t) -> T { return void(), t; })({}); std::cout << '\n';
    ([](T t) -> T { return void(), std::move(t); })({}); std::cout << '\n';
}

当由GCC-4.7.1输出(编译链接 ):

move constructor 
copy constructor 
move constructor 

为什么逗号运营商有这样的效果? 该标准说:

5.18逗号运算符[expr.comma]

1 - [...]的结果的类型和值是类型和右操作数的值; 结果是相同的价值范畴作为其右操作数[...]的。 如果右操作数的值是暂时的,结果是暂时的。

难道我错过了一些东西,允许逗号操作来影响程序的语义,或者这是gcc的一个bug?

Answer 1:

自动举动是基于资格复制省略:

§12.8 [class.copy] p32

当复制操作的省音的标准被满足或得到满足保存的事实,所述源对象是一个功能参数,以及将被复制是由一个左值所指定的对象,重载解析选择的构造的复制是第一仿佛对象是由一个rvalue指定执行。 [...]

并复制当返回表达式是一个自动对象的名称依次省音是允许的。

§12.8 [class.copy] p31

return与类返回类型的函数声明, 当表达是一种非挥发性的自动对象的具有相同的CV-不合格类型作为函数返回类型名称 (不是函数或catch子句参数其他),该复制/移动操作可以通过直接构建自动物体插入函数的返回值可以省略

使用逗号运算符插入时,表达式是不是一个自动对象的名称了,但只有一个参考一个,这抑制复制省略。



Answer 2:

t 一个本地的,指定的变量,并因此左值。 逗号操作符表现为记录。

相反,你应该问为什么return t; 允许t绑定到一个右值引用- 是真正的魔法。



文章来源: Move constructor suppressed by comma operator