逗号运算符禁止移动构造函数
Move constructor suppressed by comma operator
此程序:
#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中的一个错误?
自动移动基于复制省略的资格:
§12.8 [class.copy] p32
当满足或将满足省略复制操作的标准时,除非源对象是函数参数,并且要复制的对象是由左值指定的,否则首先执行重载解析以选择复制的构造函数,就好像对象是由右值指定的一样。[…]
当返回表达式是自动对象的名称时,允许复制省略。
§12.8 [class.copy] p31
在具有类返回类型的函数中的
return
语句中,当表达式是与函数返回类型具有相同cv不合格类型的非易失性自动对象(函数或catch子句参数除外)的名称时,可以通过将自动对象直接构造到函数的返回值中来省略复制/移动操作
插入逗号运算符后,表达式不再是自动对象的名称,而只是对一个对象的引用,这将抑制复制省略。
t
是一个局部命名变量,因此是一个左值。逗号运算符的行为与文档一样。
相反,您应该问为什么return t;
允许t
绑定到右值引用-这才是真正的魔力。
相关文章:
- 为什么不调用移动构造函数?(默认情况下只有构造器,没有别的)
- std::vector::p ush_back() 不会在 MSVC 上编译具有已删除移动构造函数的对象
- 仅包含可移动 std::map 的类的移动构造函数不起作用
- 为什么调用复制构造函数而不是移动构造函数?
- 基类中的默认析构函数禁用子类中的移动构造函数(如果有成员)
- 从具有按值捕获的 lambda 移动构造 std::函数时,移动构造函数调用两次
- 移动构造函数和右值引用
- 为什么 std::memmove 中联合的默认非平凡移动构造函数C++?
- 具有专用化的模板类中的可靠条件复制和移动构造函数
- C++:为什么不调用移动构造函数?
- 移动构造函数永远不会被调用
- C++:关于使用 Stroustrup 示例移动构造函数/赋值的问题
- 运算符+ 的规范实现涉及额外的移动构造函数
- C ++为什么在移动构造函数中需要移动/前进
- 为什么在删除"移动构造函数"时使用"复制构造函数"?
- 为什么这里不调用移动构造函数?
- 隐式移动构造函数
- 如何为具有私有成员的派生类实现移动构造函数
- 为什么不调用移动构造函数
- 是否可以避免在以下代码中复制/移动构造函数的需要?