最小可重现的示例 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
返回一个const Movable &
而不是一个Movable &
,但为什么会这样?
我知道it.first
必须是恒常的,因为键不能被弄乱,但从值中移出应该没问题。
为什么我在这里得到一个 const 引用以及如何修复代码以便我可以移动?
it.second
不是const
。
问题是,用户声明移动构造函数不仅会删除隐式声明的复制构造函数和复制赋值运算符,还会禁止移动赋值运算符的隐式声明。
因此,您的类没有移动赋值运算符,并且复制赋值运算符被删除,从而导致您在尝试将it.second
分配给另一个Movable
时看到的错误。
target[i] = move(it.second);
是一个赋值表达式,而不是变量定义或将调用构造函数的对象的其他初始化。
加
Movable& operator=(Movable&&) = default;
到您的班级,并且可以进行移动作业。
如果默认移动构造函数,则可能也希望自己默认移动赋值运算符。否则,它将调用复制赋值运算符(已删除(。在这种情况下,编译器不会为您生成移动赋值运算符。
Movable& operator=( Movable && ) = default; // move assignment