代码之家  ›  专栏  ›  技术社区  ›  code_fodder

强制转换为右值引用以“强制”返回值中的移动-澄清

  •  1
  • code_fodder  · 技术社区  · 6 年前

    #include <iostream>
    
    using namespace std;
    
    std::string get_string()
    {
      std::string str{"here is your string\n"};
      return std::move(str);  // <----- cast here?
    }
    
    int main ()
    {
      std::string my_string = std::move(get_string()); // <----- or cast here?
      std::cout << my_string;
      return 0;
    }
    

    所以我有一个简单的例子,我有一个函数,返回一个字符串的副本。我已经读到它的坏(并得到核心转储来证明它!)返回对本地temp变量的任何引用,所以我已经尝试过了。

    在作业中 main() 我不想复制构造那个字符串我想移动构造/分配这个字符串以避免复制太多的字符串。

    • 问题1:我返回一个临时变量的“副本” get_string() -但我已将返回值转换为rvalue red。这是没有意义的还是做了什么有用的事?

    • 问题2:假设问题1的答案是我不需要这么做。那么我要把temp变量的新副本移到 my_string ,还是直接移动temp变量 str 进入之内 我的\u字符串 .

    2 回复  |  直到 6 年前
        1
  •  1
  •   Vittorio Romeo    6 年前

    你不必使用 std::move 在这种情况下,由值返回的局部变量将为您“隐式移动”。这个标准有一个特别的规定。在这种情况下,你的行动是 悲观 因为它可以防止裂谷热(叮当警告这一点)。


    标准::移动 呼叫的结果 get_string() 获取字符串() 是一个 pr值 ,这意味着 my_string 强制副本省略 将确保不会发生移动/复制(使用 pr值 ).


    取决于标准和RVO是否发生。如果发生RVO,您将有0个副本和0个移动。如果你瞄准C++ 17,从 ,您保证有0个副本和0个移动。如果两者都没有发生,你可能会有一个单一的移动-我不明白为什么任何副本应该出现在这里。

        2
  •  1
  •   Maxim Egorushkin    6 年前

    std::move 返回一个局部变量。 The compiler does that for you :

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

    推荐文章