Arn*_*aud 8 c++ copy return move c++11
看完这个问题后.我创建了这个小小的测试:
class A{
public:
A(){}
A(const A&){printf("copy\n");}
A(A&&){printf("move\n");}
static A f(){
A a;
return a;}
static A g(){
A a;
return (a);}//could be return *&a; too.
static A h(){
A a;
return true?a:a;}
};
Run Code Online (Sandbox Code Playgroud)
结果是(没有RVO和NRVO):
据我所知,用于决定是否使用复制或移动的规则在12.8.32中描述:
这是指12.8.31的规则:(我只显示相关部分)
按照这些规则,我理解f和h会发生什么:
怎么样?
对我来说,它看起来很像h.我正在返回一个表达式,它不是自动对象的名称,因此我认为它会被复制但是它被移动了.这里发生了什么?
MWi*_*Wid 11
在大多数情况下,写作a或写作没有区别(a).规范的相关部分是§5.1p6(强调我的):
带括号的表达式是一个主表达式,其类型和值与所包含表达式的类型和值相同.括号的存在不会影响表达式是否为左值.除非另有说明,否则带括号的表达式可以在与可以使用所包含的表达式的上下文完全相同的上下文中使用,并且具有相同的含义.
因此,相同的推理适用于g您给出的函数的返回值f.
在升级标准C++ 14中,已经阐明了§12.8p32(强调我的):
当满足复制/移动操作的省略标准时,但不满足异常声明,并且要复制的对象由左值指定,或者当返回语句中的表达式是(可能带有括号的)id-时表达式,用于在最内层封闭函数或lambda-expression的body或parameter-declaration-clause中声明的具有自动存储持续时间的对象,首先执行重载决策以选择复制的构造函数,就像对象由rvalue指定一样.
对于那些想知道的人,当括号重要时,这是一个例子:
namespace N {
struct S { };
void f(S);
}
void g() {
N::S s;
f(s); // OK: calls N::f
(f)(s); // error: N::f not considered; parentheses
// prevent argument-dependent lookup
}
Run Code Online (Sandbox Code Playgroud)