Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/148.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么在这种情况下调用move构造函数?_C++_Constructor_Move_Nrvo - Fatal编程技术网

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 for
return[expression]

如果
[expression]
是一个左值表达式,它是在正文中声明的自动存储持续时间对象的名称(可能带括号),或者作为最里面的封闭函数或lambda表达式的参数,然后,选择用于初始化返回值的构造函数的重载解析将执行两次:首先,就好像
[expression]
是一个右值表达式(因此它可以选择移动构造函数),如果没有合适的转换可用,或者,如果所选构造函数的第一个参数的类型不是对对象类型的右值引用(可能是cv限定),则第二次执行重载解析,并将
[expression]
视为左值(因此它可以选择引用非常量的复制构造函数)

简而言之,从C++11开始,如果可能的话,
return
语句将倾向于使用move构造函数,并回退到copy构造函数。From for
return[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以来,确实存在强制返回值优化,但不存在左值优化。