为什么下面的代码不调用 std::string 的移动构造函数?
Why does the following code not invoke std::string's move constructor?
以下代码在VS2013上编译,从不调用std::string的移动构造函数(通过设置断点进行检查,而是调用const-ref-copy构造函数。
#include <iostream>
#include <string>
#include <stdlib.h> /* srand, rand */
#include <time.h> /* time */
struct foo
{
foo(std::string& str1, std::string& str2) : _str1(str1), _str2(str2) {}
~foo() { std::cout << "Either "" << _str1 << "" or "" << _str2 << "" was returned." << std::endl; }
std::string& _str1;
std::string& _str2;
};
std::string foobar()
{
std::string str1("Hello, World!");
std::string str2("Goodbye, cruel World.");
foo f(str1, str2);
srand(time(NULL));
return (rand() % 2) ? str1 : str2;
}
int main()
{
std::cout << """ << foobar() << "" was actually returned." << std::endl;
return EXIT_SUCCESS;
}
我希望foobar()中的return语句能够调用move构造函数,因为我正在返回一个local(rand()是为了防止NRVO),就像对诸如返回局部变量的std::move之类的问题的回答一样
这是因为我试图在这里为我的另一个问题添加另一个例子:https://softwareengineering.stackexchange.com/questions/258238/move-semantics-in-c-move-return-of-local-variables
C++11有一个特殊的情况,当它是一个局部变量并用作函数的返回表达式时,它允许复制/移动省略:
C++11 12.8/31"复制和移动类对象":
在具有类返回类型的函数的return语句中,当表达式是非易失性自动对象的名称(除函数或catch子句参数)具有相同cv不合格类型作为函数返回类型,复制/移动操作可以通过将自动对象直接构造到函数的返回值
但是,由于返回语句不仅仅是"非易失性自动对象的名称",因此不满足复制省略的这种情况。
后来,标准提到
C++11 12.8/32"复制和移动类对象":
当满足或将满足省略复制操作的标准时除了源对象是函数参数这一事实之外,并且要复制的对象由左值重载指定首先执行为副本选择构造函数的解析就好像对象是由右值指定的一样。如果过载解决方案失败,或者如果所选的第一个参数的类型构造函数不是对对象类型的右值引用(可能cv合格),考虑到对象作为左值。[注:此两阶段过载解决方案必须无论是否会发生复制省略,都将执行。它如果不执行省略,则确定要调用的构造函数,并且所选构造函数必须是可访问的,即使调用是消隐。——尾注]
这样,即使返回指定了左值,也可以使用移动操作。然而,这种特殊情况仅适用于第一句的条件,而在示例return
语句的情况下则不满足这些条件。
你可以强制发布:
return (rand() % 2) ? std::move(str1) : std::move(str2);
- std::string 的对象真的可以移动吗?
- 构造函数采用std::string_view与std::string并移动
- 在'string=string+s1'和"string+=s1"之间移动语义可以保存多少个复制操作?
- 在新线程中访问移动的 std::string
- 如何有效地将底层数据从 std::string 移动到其他类型的变量?
- std::string移动构造函数真的会移动吗
- std::move在将std::string移动到另一个线程时出错
- std::vector<std::string>的内容在被分配为 R 值时会被移动吗?
- 将 std::string 中的文本块向左移动 X 个字符
- 在 C++03 中将 std::string 移动到 boost::线程中
- 如果 std::string 从未被修改,它可以在创建后移动吗?
- 有没有办法将std::string移动到std::stringstream中
- 使用 std::string 参数和不可移动/可复制参数构建 std::map
- 快速将 CString 移动到 std::string
- 试图编写能够从std::string中移动语义的字符串类
- 从char*中移动std::string的构造函数
- 你能重用移动的 std::string 吗?
- 为什么下面的代码不调用 std::string 的移动构造函数?
- 为什么VS2008 std::string.erase()移动它的缓冲区?
- 使用std::string在内存中移动jpeg是否安全?