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

为何用纯右值(prvalue)直接初始化基类成员需拷贝/移动构造函数?

为什么删除拷贝构造函数的基类,在派生类初始化列表中用纯右值初始化会报错?

我们先看一个能正常编译的例子:对于删除了拷贝构造函数的类,确实可以通过纯右值(比如函数返回值)直接初始化对象,比如下面的代码:

struct B {
  B(int i, std::string s) {}
  B(const B&) = delete;
};

B Factory() {
  return {1, "ss"};
}

int main() {
  B obj(Factory());
  return 0;
}

但当添加如下派生类代码后:

struct D : public B {
  D() : B(Factory()) {}
};

会触发编译错误:

main.cpp:22:40: error: use of deleted function ‘B::B(const B&)’

问题根源

这个问题和C++标准中复制消除的规则演变有关:

首先看C++标准的相关规定:

  • 11.9.4(7)条款:

    mem-initializer中的expression-list或braced-init-list将按照9.4条款的直接初始化规则,用于初始化指定子对象(或委托构造函数中的完整类对象)。

  • 9.4(17.6.1)条款:

    若初始化表达式为纯右值,且源类型的cv非限定版本与目标类相同,则该初始化表达式将用于初始化目标对象。

从条款描述来看,基类子对象的初始化应该适用纯右值直接初始化的规则,但实际报错的原因在于:

  • 在C++17之前,复制消除(即跳过拷贝/移动构造,直接用纯右值初始化目标对象)是编译器的可选优化,而非强制要求。部分编译器在处理基类子对象的初始化时,没有执行这个优化,而是尝试调用被删除的拷贝构造函数,从而触发错误。
  • 到了C17标准,复制消除被改为强制规则,编译器必须直接用纯右值初始化目标对象,不再依赖拷贝/移动构造函数,因此这段代码在C17及更高版本中可以正常编译。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 05:12:28