Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/153.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如果我将一个局部对象移动到一个函数中,之后它仍然有效吗?_C++_C++11_Move Semantics - Fatal编程技术网

C++ 如果我将一个局部对象移动到一个函数中,之后它仍然有效吗?

C++ 如果我将一个局部对象移动到一个函数中,之后它仍然有效吗?,c++,c++11,move-semantics,C++,C++11,Move Semantics,因此,这提供了预期的输出: void f(std::string&& s) { s += " plus extra"; } int main(void) { std::string str = "A string"; f( std::move(str) ); std::cout << str << std::endl; return 0; } void f(std::string&&s) { s+=“加额外”; } 内部

因此,这提供了预期的输出:

void f(std::string&& s)
{
   s += " plus extra";
}

int main(void)
{
   std::string str = "A string";
   f( std::move(str) );
   std::cout << str << std::endl;

   return 0;
}
void f(std::string&&s)
{
s+=“加额外”;
}
内部主(空)
{
std::string str=“一个字符串”;
f(std::move(str));

std::cout
std::move
不移动任何东西。
它通过将参数强制转换为右值来指示对象可能被“从”移动

您的代码有效,未执行移动操作

如果从
s
移动并构造另一个字符串对象,则调用
f()
后,
str
的状态未指定。移动构造函数执行实际的移动操作

例如:

std::vector<std::string> sv;

void f(std::string&& s)
{
    s += " plus extra";
    sv.push_back(std::move(s));         // move s (str) into a new object
}

int main(void)
{
   std::string str = "A string";
   f(std::move(str));                 
   std::cout << str << std::endl;       // output: empty string
   std::cout << sv.back() << std::endl; // output: "A string plus extra"

   return 0;
}
std::vector sv;
void f(std::string&&s)
{
s+=“加额外”;
sv.push_back(std::move(s));//将s(str)移到新对象中
}
内部主(空)
{
std::string str=“一个字符串”;
f(std::move(str));
std::cout它是有效的,不是UB

它也是一个非常混乱的代码。
std::move(s)
只不过是对右值的转换。它本身实际上根本不会生成任何代码。它唯一的目的是将左值转换为右值,以便客户端代码可以重载左值/右值表达式(在本例中为
string

对于这种情况,您应该通过左值引用传递:

void f(std::string& s)
{
   s += " plus extra";
}
...
f( str );
或者,通过值传递并返回新字符串:

std::string f(std::string s)
{
   s += " plus extra";
   return s;
}
...
str = f( std::move(str) );

代码是有效的,因为没有执行实际的移动。以下是如何使其无效:

string f(std::string&& s) {
    std::string res(std::move(s));
    res += " plus extra";
    return res;
}

调用后,
str
的状态将是有效的,但未指定。这意味着您仍然可以为
str
分配一个新值以使其返回到有效状态,但如果不调用未指定的行为()。有关从状态移动的详细信息,请参阅。

std::move
只是将对象强制转换为右值引用。由于函数获取引用并仅对其执行某些操作,因此此处不获取所有权,因此字符串仍处于有效状态,可以安全使用

我不建议在代码中使用这一点,因为它是误导性的,因为很多人会认为你的字符串是无效的,因为拥有所有权是RValk引用的主要用途,因此<代码> STD::移动< /代码> ./P> 如果您确实需要以这种方式调用此函数,我建议您编写以下内容:

std::string myString{"a string"};

// leave a comment here to explain what you are doing.
f(static_cast<std::string&&>(myString));
std::string myString{“a string”};
//在这里留下评论来解释你在做什么。
f(静态_cast(myString));

但是,请注意,如果函数
f
采用值而不是引用,那么您的示例将完全不同。在这种情况下,同时使用
std::move
static\u cast
调用它将使字符串无效。

是的,它仍然有效,但它包含的内容未定义。您应该调用的唯一方法是移动后的字符串将用新内容替换其内容。例如
str.clear()
.Related:字符串没有移动,右值引用被发送,所有权也没有被剥夺。这段代码是完全有效的。这里没有UB,也没有未定义的内容,或者其他任何意思。这个例子实际上没有移动字符串。顺便说一句,它不必移动,但一般来说,当我看到一个函数接受R值引用,我希望它使用对象。可能还需要提到复制省略,以及在移动构造函数/移动赋值运算符之外,
&&
在很大程度上是不必要的。