为什么不调用 std::string move 构造函数?
Why wasn't std::string move constructor called?
我有这个例子:
#include <string>
#include <iostream>
class Test {
private:
std::string str;
public:
Test(std::string &&str_) :
str(str_)
{}
const std::string &GetStr()
{
return str;
}
};
int main(int argc, char *argv[])
{
std::string there("1234567890");
std::cout << "1. there: " << there << 'n';
Test t1(std::move(there));
std::cout << "2. there: " << there << 'n';
std::cout << "3. there: " << t1.GetStr() << 'n';
}
它给出输出
$ ./a.out
1. there: 1234567890
2. there: 1234567890
3. there: 1234567890
这是在linux上使用gcc 5.1.1。虽然there
字符串在移动后将保持有效但不确定的状态,但如果调用std::string移动构造函数,则此实现似乎会移动(而不是复制)该字符串。
如果我用str(std::move(str_))
替换初始化器str(str_)
,我会得到以下输出:
$ ./a.out
1. there: 1234567890
2. there:
3. there: 1234567890
这表明现在使用了std::string移动构造函数,但为什么在我的第一个示例中没有调用std::string(std::string &&)
呢?
您应该执行
public:
Test(std::string &&str_) :
str(std::move(str_))
{}
str_
确实有一个名称,是一个命名对象,所以它不会作为右值引用传递给任何函数。
标准委员会做出的设计选择可以防止将其视为右值,因此您不会无意中对其进行修改。特别是:str_
-do的类型是对string
的左值引用,但str_
不被认为是右值,因为它是一个命名对象。
您必须通过向std::move
添加一个调用来明确您的意图。这样做意味着你希望str_
是一个右值,并且你知道这个选择的所有后果。
因为左值引用总是获胜!这就是为什么需要显式指定std::move
。
允许通过类型形成对引用的引用模板或typedef中的操作,在这种情况下引用折叠规则适用:右值引用到右值引用折叠对于左值参考,所有其他组合形成左值参考:
typedef int& lref;
typedef int&& rref;
int n;
lref& r1 = n; // type of r1 is int&
lref&& r2 = n; // type of r2 is int&
rref& r3 = n; // type of r3 is int&
rref&& r4 = 1; // type of r4 is int&&
从这里拍摄。
相关文章:
- 使用仅使用一次的变量调用的复制构造函数.这可能是通过调用move构造函数进行编译器优化的情况吗
- 添加自定义析构函数时,Move 构造函数在派生类中消失
- 将向量从 N1 缩小到 N2 项,而不触发默认构造函数并仅使用 move 语义
- 为什么 std::move 不将默认移动构造函数中的源变量更改为默认值?
- std::映射,只有move构造函数可用
- 为什么我的代码中没有调用move构造函数
- std::转换move构造函数的模板专业化的变体
- std::tuple默认构造函数,带有move可构造元素
- 如何调用move构造函数
- 复制初始化:为什么即使关闭了复制省略,也没有调用move或copy构造函数
- 为什么我们需要在构造函数的初始化列表中使用 std::move?
- 在构造函数中初始化成员时,是否应该在成员上使用 std::move?
- 我可以将 std::move 与不提供 move 构造函数的类一起使用吗?
- 基于范围的 std::move 调用意外复制构造函数
- C++编译错误是由于使用 std::move 时运动构造函数与其他非运动构造函数之间的冲突
- 为什么noexcept move构造函数在向量重新分配期间没有被调用
- 使用 Move 语义在构造函数中初始化类成员
- 为什么在声明析构函数时必须声明 copy & move 构造函数?
- 我应该总是在构造函数中使用 std::move 吗?
- 如果我们只定义复制构造函数/oper=,为什么移动构造函数/move赋值没有隐式声明和定义为删除