是否可以将 std::move 对象移出函数?(C++11)

这个程序试图将一个字符串移出函数并用它来构造另一个字符串:

This program tries to move a string out of a function and use it for the construction of another string:

#include <iostream>
#include <string>
#include <utility>

std::string && Get_String(void);

int main(){

    std::string str{Get_String()};
    std::cout << str << std::endl;

    return 0;
}

std::string && Get_String(void){

    std::string str{"hello world"};

    return std::move(str);
}

程序可以编译,但在执行时出现段错误.

The program compiles, but segfaults upon execution.

这是我的基本原理:Get_String 将创建一个本地字符串.在字符串超出范围之前,需要制作并返回该字符串的副本.该副本将用于在 main 中构造字符串.但是,如果我将字符串移出函数,则不需要进行复制.

This was my rationale: Get_String will create a local string. A copy of that string will need to be made and returned before the string goes out of scope. That copy will be used to construct the string in main. However, If I moved the the string out of the function, no copy would need to be made.

为了理解移动语义,有人可以解释为什么我在做什么,可能没有意义.是否可以将对象移出函数?

In an attempt to understand move semantics, could someone explain why what I'm doing, probably makes no sense. Is it possible to move objects out of a function?


如果我从以下位置更改函数签名,它会编译并正确运行:


It compiles and runs correctly if I change the function signature from:

std::string && Get_String(void);

std::string Get_String(void);  

在这种情况下,在返回期间移动字符串是否仍然更有效?

Is it still more efficient to move the string during the return in this case?

推荐答案

鉴于这个例子,

X foo ()
{
  X x;    
  return x;
}

保证以下行为:

? 如果 X 具有可访问的复制或移动构造函数,则编译器可能会选择删除副本.这就是所谓的(命名的)返回值优化 ((N)RVO),甚至在 C++11 之前就已指定,并且是大多数编译器都支持.
? 否则,如果X 有移动构造函数,则x 被移动.
? 否则,如果X 具有复制构造函数,则复制x.
? 否则,会发出编译时错误.

? If X has an accessible copy or move constructor, the compiler may choose to elide the copy. This is the so-called (named) return value optimization ((N)RVO), which was specified even before C++11 and is supported by most compilers.
? Otherwise, if X has a move constructor, x is moved.
? Otherwise, if X has a copy constructor, x is copied.
? Otherwise, a compile-time error is emitted.

还要注意,如果返回的对象是本地非静态对象,则返回右值引用是错误的:

Note also that returning an rvalue reference is an error if the returned object is a local nonstatic object:

X&& foo ()
{
  X x;
  return x; // ERROR: returns reference to nonexistent object
}

右值引用是一个引用,在引用本地对象时返回它意味着你返回对不再存在的对象的引用.是否使用 std::move() 不很重要.

An rvalue reference is a reference, and returning it while referring to a local object means that you return a reference to an object that doesn’t exist any more. Whether std::move() is used doesn’t matter.

std::move() 并没有真正移动对象;它只会把左值变成右值.

std::move() doesn't really move object; it only turns lvalues into rvalues.

相关文章