C++ 为什么在这种情况下调用move构造函数?
我有以下代码:C++ 为什么在这种情况下调用move构造函数?,c++,constructor,move,nrvo,C++,Constructor,Move,Nrvo,我有以下代码: SomeClass func() { SomeClass someObject; someObject.mutate("some text"); return someObject; } int main() { func(); return 0; } 其中SomeClass只在构造函数中记录一些内容,以便我可以验证调用的内容 在发布版本中,我有以下几点: default constructor 由于复制/移动省略,这是有意义的。 我
SomeClass func()
{
SomeClass someObject;
someObject.mutate("some text");
return someObject;
}
int main()
{
func();
return 0;
}
其中SomeClass只在构造函数中记录一些内容,以便我可以验证调用的内容
在发布版本中,我有以下几点:
default constructor
由于复制/移动省略,这是有意义的。
我想关闭返回值优化。
对于调试版本,我有以下输出:
default constructor
move constructor
我认为我可以安全地假设NRVO si关闭。
我真想知道为什么调用move构造函数而不是copy构造函数。我(可能是错误的)理解是,由于func中的someObject是左值,因此应该使用复制构造函数而不是移动构造函数初始化返回对象
我错过了什么?有人能指出标准中说明这种情况的段落吗?From forreturn[expression]代码>:
如果[expression]
是一个左值表达式,它是在正文中声明的自动存储持续时间对象的名称(可能带括号),或者作为最里面的封闭函数或lambda表达式的参数,然后,选择用于初始化返回值的构造函数的重载解析将执行两次:首先,就好像[expression]
是一个右值表达式(因此它可以选择移动构造函数),如果没有合适的转换可用,或者,如果所选构造函数的第一个参数的类型不是对对象类型的右值引用(可能是cv限定),则第二次执行重载解析,并将[expression]
视为左值(因此它可以选择引用非常量的复制构造函数)
简而言之,从C++11开始,如果可能的话,return
语句将倾向于使用move构造函数,并回退到copy构造函数。From forreturn[expression]代码>:
如果[expression]
是一个左值表达式,它是在正文中声明的自动存储持续时间对象的名称(可能带括号),或者作为最里面的封闭函数或lambda表达式的参数,然后,选择用于初始化返回值的构造函数的重载解析将执行两次:首先,就好像[expression]
是一个右值表达式(因此它可以选择移动构造函数),如果没有合适的转换可用,或者,如果所选构造函数的第一个参数的类型不是对对象类型的右值引用(可能是cv限定),则第二次执行重载解析,并将[expression]
视为左值(因此它可以选择引用非常量的复制构造函数)
简言之,自C++11以来,return
语句在可能的情况下更倾向于使用移动构造函数,并回退到复制构造函数。同样来自C++11标准,12.8复制和移动对象,第285页,第32项:
当满足或将满足省略复制操作的条件时,除了源
对象是函数参数,要复制的对象由左值指定,重载分辨率为
选择首先执行复制的构造函数,就像对象由右值指定一样。如果过载
解析失败,或者所选构造函数的第一个参数的类型不是对的右值引用
对象的类型(可能是cv限定的)重载解析将再次执行,并将对象视为
左值。[注意:无论复制省略是否会发生,都必须执行此两阶段重载解析
它确定在未执行省略时要调用的构造函数,以及所选的构造函数
即使电话被省略,也必须可访问。-结束说明]
同样来自C++11标准,12.8复制和移动对象,第285页,第32项:
当满足或将满足省略复制操作的条件时,除了源
对象是函数参数,要复制的对象由左值指定,重载分辨率为
选择首先执行复制的构造函数,就像对象由右值指定一样。如果过载
解析失败,或者所选构造函数的第一个参数的类型不是对的右值引用
对象的类型(可能是cv限定的)重载解析将再次执行,并将对象视为
左值。[注意:无论复制省略是否会发生,都必须执行此两阶段重载解析
它确定在未执行省略时要调用的构造函数,以及所选的构造函数
即使电话被省略,也必须可访问。-结束说明]
@是的,我删除了我的评论。再看一眼,事情并不是这样的。但是,请注意,自C++17以来,确实存在强制返回值优化,但不适用于左值。@JollyRoger是的,我删除了我的注释。再看一眼,事情并不是这样的。但是,请注意,自C++17以来,确实存在强制返回值优化,但不存在左值优化。