首页 文章

如何在函数返回期间使用std :: string移动语义? [重复]

提问于
浏览
18

可能重复:C 11 rvalues并移动语义混淆

我认为是正确的

std::string GetLine()
{
std::string str;
std::getline(std::cin, str);
return std::move(str);
}

但是在这个链接http://www.cprogramming.com/c++11/rvalue-references-and-move-semantics-in-c++11.html(检查 Headers 部分从函数返回显式的右值引用)

这是#1谷歌搜索命中移动语义显示类似的功能签名

int&& GetInt()
{
int x = 0;
// code here
return std::move(x);
}

从我在其他地方读到的&&表示rvalue reference 所以在这种情况下它返回对不存在的对象的引用 .

那是哪个呢?

(是的,我知道移动一个int没有真正的好处,但问题是在第一个函数中是否使用std :: string或std :: string &&的返回类型 . 如果这是应该对所有类型执行的方式 . )

3 回答

  • 4

    如果 str 是局部变量,则无需说 return std::move(str); :如果变量满足返回值优化的条件,则在 return 语句中,变量将绑定到右值引用 .

    此外,请注意,您可能不应该返回对局部变量的引用,既不是左值也不是右值引用 .

    总而言之,你应该:

    int foo() { int x; /*...*/ return x; }
    
    std::string bar() { std::string str; /*...*/ return str; }
    
  • 31

    您完全正确 int&& GetInt() 示例是错误的,并且正在返回对被销毁对象的引用 . 但是,除非我错过了,否则您发布的链接实际上并未显示任何返回对局部变量的引用的代码 . 相反,我看到对返回的全局变量的引用,这没关系 .

    以下是返回时使用移动语义的方法:

    std::string func()
    {
        std::string rv;
        /* ... */
        return rv;
    }
    

    返回对象时通常不应使用 std::move() . 这样做的原因是任何时候RVO都可以隐式允许移动,并且使用 std::move() 将抑制RVO . 所以使用 std::move() 将永远不会更好,往往会比正常返回更糟糕 .


    同样,使用 std::move() 可能比简单地命名要返回的变量更糟糕,因为它会抑制返回值优化 . 返回值优化允许将对象返回给调用者,而无需复制该对象

    在具有类返回类型的函数的return语句中,当表达式是非易失性自动对象(函数或catch子句参数除外)的名称时,具有与函数返回类型相同的cv-unqualified类型,通过将自动对象直接构造到函数的返回值中,可以省略复制/移动操作 - [class.copy] 12.8 / 31

    但是使用 std::move() 可以防止返回表达式成为您要返回的对象的名称 . 相反,表达式更复杂,不再允许语言对其进行特殊处理 .

    仅命名对象的原因并不比使用 std::move() 更糟糕,因为还有另一条规则说表达式已经可以被视为右值而不需要 std::move() .

    当满足或将满足复制操作的省略标准时,除了源对象是函数参数,并且要复制的对象由左值指定,重载决策选择复制的构造函数首先执行,好像对象是由右值指定的 .

  • 8

    回答这个问题,回复一下: string . 不要 move 任何东西,而是使用(依赖)RVO:

    std::string func()
    {
        std::string rv;
        /* ... */
        return rv;
    }
    

    这通常应该如何完成 . 您不能将(r值或非r)值引用返回临时值 .

相关问题