You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何std::pair允许从含删除移动构造的类右值初始化?

为什么std::pair允许从不可移动类型的右值初始化?

首先看这个不可移动类型的定义:

struct Do_not_move {
    Do_not_move() = default;
    Do_not_move(const Do_not_move&) = default;
    Do_not_move(Do_not_move&&) = delete;
private:
    int dummy;
};

我们会发现一个有意思的现象:

  • std::pair<int, Do_not_move> p(0, std::move(dnm)); 这段代码能正常运行
  • 但像std::vector<Do_not_move> v{std::move(dnm)};、std::set<Do_not_move> s{std::move(dnm)};、std::any a{std::move(dnm)};这类代码都会报错

那为啥std::pair这么特殊?

其实核心原因在于std::pair的构造函数参数处理逻辑:

当你用std::move(dnm)作为参数传给std::pair的构造函数时,虽然你传的是右值,但std::pair的构造函数并不会强制要求用移动构造来初始化它的成员。它会把传入的第二个参数(类型是Do_not_move&&)绑定到构造函数的参数上,然后在初始化pair的Do_not_move成员时,因为Do_not_move的移动构造被删除了,编译器会自动退而求其次,调用可用的拷贝构造函数——而这个类型的拷贝构造是默认存在的,所以整个初始化过程能正常完成。

而像vector、set这类容器,它们在处理初始化元素的时候,会尝试直接用传入的右值来构造容器内的元素,也就是会优先调用移动构造函数。一旦移动构造被删除,编译器找不到可用的构造方式,自然就报错了。std::any也是类似的逻辑,它在存储对象时会尝试移动构造,失败就会直接报错。

简单总结一下:std::pair的构造函数没有强制绑定传入参数的值类别(左值/右值)来构造成员,而是允许编译器根据可用的构造函数自动选择最优方案;而其他容器/工具类则会更严格地按照传入值的类型来尝试构造,当移动不可用时就直接失败。

内容的提问来源于stack exchange,提问作者xskxzr

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:07:40