std::pair配合const std::unique_ptr使用时报无匹配函数调用错误
问题根本原因
你遇到的现象是C++类特殊成员函数的隐式生成规则、std::unique_ptr的不可拷贝特性、拷贝消除规则三者共同作用的结果。
前置基础规则
std::unique_ptr是独占型智能指针,仅支持移动语义,无拷贝构造/拷贝赋值函数。- C++标准规定:若用户显式声明了析构函数(哪怕是
=default实现,也算用户声明),编译器将不会隐式生成移动构造函数和移动赋值运算符。 - 若类包含不可拷贝的非静态成员,编译器隐式生成的拷贝构造/拷贝赋值运算符会被定义为弃置(deleted)。
- 若类的非静态成员是const修饰的可移动类型,移动构造函数也无法正常生成(移动操作需要修改源对象的成员,const修饰后无法修改。
- C++17起强制要求纯右值的拷贝消除:当用临时对象初始化同类型对象时,直接在目标对象地址构造,无需调用拷贝/移动构造函数。
各场景编译结果解释
(4)行始终编译正常
代码:TestClass myTestClass = TestClass("myTestClass");
这行触发了强制拷贝消除,不需要调用TestClass的拷贝/移动构造函数,直接在myTestClass的内存地址构造对象,所以不管TestClass是否支持拷贝/移动都不影响编译。
(5)行始终编译失败
代码:std::make_pair("myTestClassKey", myTestClass);myTestClass是左值,要将其存入std::pair必须调用拷贝构造,或是显式通过std::move转为右值触发移动构造:
- 你的
TestClass包含std::unique_ptr成员,拷贝构造函数被默认弃置,无法拷贝; - 左值不会自动触发移动语义,
std::make_pair尝试调用拷贝构造失败,因此所有场景下都无法编译。
如果要让这行可编译,可修改为:
std::make_pair("myTestClassKey", std::move(myTestClass));
(6)行仅在注释(1)行、使用(2)行时可编译
代码:std::make_pair("myTestClassKey", TestClass("myTestClass"));
这里传入的TestClass是临时右值,std::make_pair会尝试调用移动构造将对象存入pair:
- 保留(1)行时:你显式声明了析构函数,编译器不隐式生成移动构造,无可用的拷贝/移动构造,编译失败。
- 使用(3)行时:成员是
const std::unique_ptr,移动构造需要修改源对象的str成员,const修饰后无法修改,移动构造无法生成,编译失败。 - 只有注释(1)行、使用(2)行时:编译器会隐式生成可用的移动构造函数,右值可以触发移动构造,因此编译正常。
内容的提问来源于stack exchange,提问作者LosConikos
相关产品推荐
相关产品推荐

