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

删除拷贝构造函数后std::make_unique编译失败的原因及疑问

C++删除拷贝构造函数后移动构造函数的隐式生成问题

代码示例与问题现象

无法编译的代码

struct A {
    A() = default;
    A(const A& other) = delete;
};

int main()
{
  auto a = A();
  auto u = std::make_unique<A>(std::move(a));
}

这段代码在支持C++17的blaze编译器下编译失败,错误信息为:call to implicitly-deleted copy constructor

可以编译的代码

struct A {
    A() = default;
    A(const A& other) = delete;
    A(A&& other) = default;
};

int main()
{
  auto u = std::make_unique<A>(A());
}

疑问

  • 第一段代码明明使用了std::move(a)将对象转为右值,为什么不调用移动构造函数,反而触发拷贝构造函数的错误?
  • 删除拷贝构造函数会导致移动构造函数被隐式删除吗?为什么显式添加A(A&& other) = default;就能解决编译问题?

解答

  1. C++标准的隐式生成规则
    当类中存在用户显式声明的拷贝构造函数(包括被删除的版本)时,编译器不会自动生成默认的移动构造函数。这是C++11及后续标准的明确规定——拷贝操作的用户声明会抑制移动操作的隐式生成。

  2. 第一段代码编译失败的原因
    在第一段代码中,struct A仅删除了拷贝构造函数,没有显式声明移动构造函数,因此编译器不会为它生成默认的移动构造函数。当调用std::make_unique<A>(std::move(a))时,虽然std::move(a)将a转为右值,但由于没有可用的移动构造函数,编译器会尝试回退到拷贝构造函数来完成对象构造。但拷贝构造函数已经被显式删除,最终触发了“调用被隐式删除的拷贝构造函数”的错误。

  3. 第二段代码编译通过的原因
    第二段代码中显式添加了A(A&& other) = default;,这会要求编译器生成符合默认行为的移动构造函数。此时std::make_unique<A>(A())可以通过移动构造函数来传递右值临时对象,因此编译正常通过。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 22:40:40