1

最小可复制示例cpp.sh/2nlzz

#include <iostream>
#include <string>
#include <vector>
#include <unordered_map>

using namespace std;
int main()
{
  struct Movable {
    Movable() = default;
    Movable ( Movable && ) = default; // move constructor
    vector<int> payload;
  };
  unordered_map<int, Movable> map;
  vector<Movable> target(10);
  int i = 0; 
  for(auto& it : map) {
    target[i] = move(it.second);
    ++i;
  }
}

给我

19:15: error: use of deleted function 'main()::Movable& main()::Movable::operator=(const main()::Movable&)'
10:10: note: 'main()::Movable& main()::Movable::operator=(const main()::Movable&)' is implicitly declared as deleted because 'main()::Movable' declares a move constructor or move assignment operator

我确实为它定义了一个移动构造函数,Movable并希望它只被移动,而不是被复制,所以它不使用常规赋值运算符很好,我猜它试图使用它,因为it.second返回 aconst Movable &而不是 a Movable &,但为什么呢?

我知道这it.first必须是 const,因为键不能被弄乱,但是从值中移动应该没问题。

为什么我在这里得到一个 const 引用,我怎样才能修复代码以便我可以移动?

4

2 回答 2

3

it.second不是const

问题是用户声明移动构造函数不仅删除了隐式声明的复制构造函数和复制赋值运算符,而且还禁止了移动赋值运算符的隐式声明。

因此,您的班级没有移动赋值运算符,并且复制赋值运算符被删除,导致您在尝试分配it.second给另一个时看到的错误Movable

target[i] = move(it.second);

是一个赋值表达式,而不是变量定义或将调用构造函数的对象的其他初始化。

添加

Movable& operator=(Movable&&) = default;

到你的班级和移动作业将是可能的。

于 2020-01-30T18:13:35.550 回答
3

如果您默认移动构造函数,您可能还想自己默认移动赋值运算符。否则它将调用复制赋值运算符(已删除)。在这种情况下,编译器不会为您生成移动赋值运算符。

Movable& operator=( Movable && ) = default; // move assignment
于 2020-01-30T18:15:37.253 回答