为什么插入 std::unordered_set 调用复制构造函数?

IAm*_*ser 3 c++ insert unordered-set

我有一个 std::unordered_set 指针。如果我做

int main()
{
  std::unordered_set<std::unique_ptr<int>> set;
  set.insert(std::make_unique(3));
}
Run Code Online (Sandbox Code Playgroud)

一切正常并插入调用移动构造函数(我认为)。但是我有一个类似于以下代码的不同情况

std::unordered_set<std::unique_ptr<int>> set;
void add(const std::unique_ptr<int>& obj) {set.insert(obj);}

int main
{
  std::unique_ptr<int> val = std::make_unique<int>(3);
  add(std::move(val));
}
Run Code Online (Sandbox Code Playgroud)

这不会编译。它给

状态错误 C2280 'std::unique_ptr<int,std::default_delete>::unique_ptr(const std::unique_ptr<int,std::default_delete> &)':试图引用已删除的函数

这意味着它正在尝试调用复制构造函数(对吗?)。所以问题是:为什么 insert 在函数内部时不移动对象?我还尝试将指针传递给 unique_ptr 甚至在几乎所有地方添加 std::move 但始终调用复制构造函数

Sam*_*hik 6

void add(const std::unique_ptr<int>& obj) 
Run Code Online (Sandbox Code Playgroud)

它归结为一些基本的东西:根据定义,你不能移动一个恒定的对象。“移动”基本上意味着从移动的对象中取出内脏,并将所有内脏推入新的移动对象中(以最有效的方式,外科医生的精确度)。如果移动的对象是const. 这是触不可及的。它必须保持其原始原始状态。

如果参数是右值引用,您应该能够做到这一点:

void add(std::unique_ptr<int>&& obj) {set.insert(std::move(obj));}
Run Code Online (Sandbox Code Playgroud)