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

时间:2012-08-17 18:42:26

标签: c++ c++11 move-semantics

  

可能重复:
  C++11 rvalues and move semantics confusion

我认为正确的是

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 (检查标题部分从函数返回显式的右值引用)

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

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

从我在其他地方阅读的内容&&表示右值引用,因此在这种情况下,它返回对不存在的对象的引用。

那是哪个?

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

3 个答案:

答案 0 :(得分:32)

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

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

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

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


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

  

在具有类返回类型的函数中的return语句中,何时   表达式是非易失性自动对象的名称(其他   比函数或catch子句参数)与之相同   cv-unqualified type作为函数返回类型,copy / move   通过直接构造自动对象可以省略操作   进入函数的返回值

     

- [class.copy] 12.8 / 31

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

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

  

当符合或将要执行复制操作的标准时   因为源对象是一个函数参数这个事实,   并且要复制的对象由左值,超载指定   首先执行选择复制的构造函数的分辨率   好像对象是由右值指定的。

答案 1 :(得分:8)

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

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

通常应该这样做。您不能将(r值或非r值)引用返回临时。

答案 2 :(得分:4)

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

另外,请注意,您可能不应该返回对局部变量的引用,也不应该返回左值和右值引用。

总而言之,你应该:

int foo() { int x; /*...*/ return x; }

std::string bar() { std::string str; /*...*/ return str; }