【发布时间】:2014-10-07 18:03:08
【问题描述】:
以下代码,在 VS2013 上编译,从不调用 std::string 的移动构造函数(通过设置断点检查,而是调用 const ref 复制构造函数。
#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 语句调用移动构造函数,因为我正在返回一个本地(rand() 是为了防止 NRVO),就像对Returning std::move of a local variable等问题的回答所说的那样
上下文是我试图在此处为我的另一个问题添加另一个示例:https://softwareengineering.stackexchange.com/questions/258238/move-semantics-in-c-move-return-of-local-variables
【问题讨论】:
-
如果删除
foo变量定义,它是否使用移动构造函数?我猜编译器足够聪明,可以知道您已经引用了使移动无效的字符串(再次猜测)。 -
不,如果我这样做,它仍然使用复制构造函数。
-
返回的“先尝试右值”仅适用于“如果满足或将满足复制省略标准,除非源对象是函数参数这一事实”。在 C++14 中,它扩展到 return 语句直接命名本地对象的所有情况。 (有关标准的完整引用,请参阅this answer。)您的条件表达式两者都不是。
-
你说你返回的是本地人。你不。
(rand() % 2) ? str1 : str2不是本地人。 -
@T.C. - 就是这样,将其更改为 if/else 而不是三元运算符使其使用移动构造函数。我似乎有点懒惰(尽管从语义上看它似乎不应该有所作为)