C++ C++;:我应该在return语句中显式使用std::move()来强制移动吗?

C++ C++;:我应该在return语句中显式使用std::move()来强制移动吗?,c++,nrvo,stdmove,C++,Nrvo,Stdmove,编辑:这不是一个重复的问题,因为这个问题询问的是编译器在O0中的决定 据说名称返回值优化(NRVO)是许多编译器支持的优化。但这是一个必须的还是只是一个很好的优化 我的情况是,为了便于调试,我希望使用-O0(即无优化)进行编译,但我还希望为返回对象(比如向量)的返回语句启用NRVO。如果NRVO不是必须的,编译器可能不会在-O0模式下执行。在这种情况下,我应该更喜欢以下代码: std::vector<int> foo() { std::vector<int> v(

编辑:这不是一个重复的问题,因为这个问题询问的是编译器在O0中的决定

据说名称返回值优化(NRVO)是许多编译器支持的优化。但这是一个必须的还是只是一个很好的优化

我的情况是,为了便于调试,我希望使用
-O0
(即无优化)进行编译,但我还希望为返回对象(比如向量)的返回语句启用NRVO。如果NRVO不是必须的,编译器可能不会在
-O0
模式下执行。在这种情况下,我应该更喜欢以下代码:

std::vector<int> foo() {
    std::vector<int> v(100000,1); // an object that is really big..
    return std::move(v);  // explicitly move
}
std::vector foo(){ 向量v(100000,1);//一个非常大的对象。。 返回std::move(v);//显式移动 } 下面这个

std::vector<int> foo() {
    std::vector<int> v(100000,1);
    return v;    // copy or move?
}
std::vector foo(){ 标准::向量v(100000,1); 返回v;//复制还是移动? } 编辑:我使用的编译器是GCC6,但我希望代码独立于编译器。

您应该更喜欢它

std::vector<int> foo() {
    std::vector<int> v(100000,1);
    return v;    // move or NRVO
}
std::vector foo(){ 标准::向量v(100000,1); 返回v;//移动或NRVO } 结束

std::vector foo(){ 标准::向量v(100000,1); 返回std::move(v);//move }
第二个代码段阻止NRVO,在最坏的情况下,两者都会移动构造。

返回值是被复制还是被移动取决于函数的返回类型及其调用上下文。函数内部发生的任何事情都与此无关。请参阅
move
是多余的,因为该值已经是右值(xvalue),并且禁止复制elison。所以这只是总体上的悲观。另外,不要优化未优化的构建。替代复制:您唯一关心的应该是优化算法的正确性和选择。代码优化是编译器关心的问题。几乎总是喜欢按值返回而不是按r值引用返回。为什么移动构造不好?我认为复制构造是不必要的,因此是不好的。在第二个代码段中,move调用阻止了NRVO,因此您只有move构造,这并不坏,但我们在第一个代码段中使用了更好或相等的代码,代码更短。并非所有的移动都是免费的。某些移动需要额外的工作,以确保从对象移动的对象处于有效状态<例如,code>unordered_map将为一个moved from对象分配存储桶。@Chad:仅在某些实现中。libc++没有。我怀疑libstdc++没有。(N) RVO和移动不是一回事。RVO在C++11之前就已经存在了——它只是编译器可以采取的一种允许的优化方法。正确的是,复制构造函数永远不会被调用-此时
v
是一个右值(确切地说是一个x值),因此接受右值的构造函数(移动构造函数)比不接受右值的构造函数(复制构造函数)更匹配。
std::vector<int> foo() {
    std::vector<int> v(100000,1);
    return std::move(v);    // move
}