我知道在以下情况下,编译器可以自由地移动构造来自makeA
(但也可以自由地删除副本或完全移动):
struct A
{
A(A&);
A(A&&);
};
A makeA()
{
A localA;
return localA;
}
我想知道编译器是否允许构造类型的对象A
来自类型的本地对象B
如果是在 return 语句中构造的,则通过右值引用。换句话说,在下面的例子中,编译器是否允许选择A
的构造函数4的返回值?
struct B { };
struct A {
A(A&); // (1)
A(A&&); // (2)
A(B&); // (3)
A(B&&); // (4)
};
A makeA()
{
B localB;
return localB;
}
我问这个问题是因为在我看来,允许本地类型对象的逻辑相同A
在 return 语句中被视为右值也应该允许任何类型的本地被视为右值,但我找不到这种性质的任何示例或问题。
这种情况的规则在 2011 年和 2014 年之间发生了变化。编译器现在应该处理localB
作为右值。
适用的规则为return
语句可以在 §12.8 [class.copy]/p32 中找到,它以 C++14 读取(引用 N3936,强调我的):
当满足复制/移动操作的省略条件时,但是
不是为了一个异常声明,要复制的对象是
由左值指定,或当 return 中的表达式
语句是一个(可能带括号)id-表达式这命名了一个
在主体中声明具有自动存储期限的对象或参数声明子句最里面的封闭函数或lambda 表达式,首先执行重载决策以选择副本的构造函数,就好像该对象是由
右值。如果第一次重载决议失败或未执行,
或者如果所选构造函数的第一个参数的类型是
不是对象类型的右值引用(可能是 cv 限定的),
再次执行重载决策,将对象视为
左值。
粗体条款由以下人员添加CWG 第 1579 期,明确要求转换移动构造函数A::A(B&&)
被叫到这里。这是在 GCC 5 和 Clang 3.9 中实现的。
早在 2011 年,这个“先尝试右值”规则就与复制省略的标准密切相关(引用 N3337):
当满足或将满足复制操作省略的标准时
满足保存源对象是函数参数的事实,
并且要复制的对象由左值、重载指定
首先执行选择副本构造函数的决议
就好像该对象是由右值指定的一样。
由于复制省略必然要求两者具有相同的类型,因此本段不适用,编译器必须使用A::A(B&)
构造函数。
请注意,由于 CWG 1579 被视为针对 C++11 的 DR,因此编译器即使在 C++11 模式下也应实现其解析。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)