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

删除移动构造函数后C++列表初始化报错?如何恢复默认行为?

问题分析与解决

报错原因

  1. 聚合体身份丢失:原结构体foo属于C++标准定义的聚合体,因此foo{42}可以通过聚合初始化直接对成员bar赋值,完全不需要依赖类的构造函数。但当你显式添加foo(foo&&) = delete;(哪怕是删除移动构造函数),foo就不再满足聚合体的判定条件——聚合体要求类/结构体不能存在任何用户声明的构造函数(包括删除的构造函数)。
  2. 默认构造函数被禁用:根据C++规则,只要类存在用户声明的构造函数(哪怕是删除的移动构造),编译器就不会自动生成默认构造函数。
  3. 无匹配构造函数可用:此时foo{42}不再是聚合初始化,编译器会尝试寻找合适的构造函数创建临时对象,但foo既没有默认构造函数,也没有自定义的int参数构造函数,因此编译器报错(部分编译器会误报为找不到默认构造函数)。

恢复初始化的可行方案

方案1:显式定义int参数构造函数

直接为foo添加接受int的构造函数,适配foo{42}的初始化方式:

struct foo {
    int bar;
    foo(int b) : bar(b) {}
    foo(foo&&) = delete;
};

此时const auto baz = foo{42};会通过这个自定义构造函数完成对象创建。

方案2:显式生成默认构造+指定初始化器(C++20+)

显式让编译器生成默认构造函数,同时使用C++20支持的非聚合体指定初始化器:

struct foo {
    int bar;
    foo() = default; // 显式要求编译器生成默认构造
    foo(foo&&) = delete;
};

// 使用指定初始化器直接赋值成员
const auto baz = foo{.bar=42};

方案3:直接使用指定初始化器(C++20+)

C++20允许对非聚合体的public成员使用指定初始化器,无需额外定义构造函数:

struct foo {
    int bar;
    foo(foo&&) = delete;
};

// 直接指定成员初始化
const auto baz = foo{.bar=42};

方案4:保留聚合体属性(不删除移动构造)

如果不需要严格禁止移动,仅想保留原有的聚合初始化方式,可以删除foo(foo&&) = delete;,让foo继续作为聚合体,编译器会自动生成移动构造函数。若必须禁止移动,只能选择前面的方案。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 22:24:28