动态数组成员必须在构造函数初始化列表中用new初始化,不能在函数体内赋值,否则会引发默认构造+赋值低效路径、const/引用成员无法赋值、指针未初始化导致delete崩溃等问题。

动态数组在构造函数里不能直接用 new 表达式初始化成员变量——必须用初始化列表,否则会触发默认构造 + 赋值的低效路径,甚至编译失败。
为什么不能在构造函数体里 new 动态数组
成员变量是类的一部分,其生命周期始于构造函数执行前。如果在函数体内写 arr = new int[n],说明 arr 已经被默认初始化(对指针类型就是未定义值),此时再赋值属于“先默认构造、再赋值”,不仅浪费(比如对 std::string 成员会多调一次默认构造),还可能出错(如 arr 是 const 或引用类型,根本无法赋值)。
- 指针成员未显式初始化时值是随机的,
delete[]会崩溃 - 若类有
const或引用成员,构造函数体里无法赋值,必须靠初始化列表 - 对自定义类型数组(如
MyClass*),new MyClass[n]会调用n次默认构造——但你可能想传参构造,这就做不到
正确做法:用初始化列表 + new 表达式
把 new 放进初始化列表,让指针成员从诞生起就指向有效内存。注意:这里只负责分配,不负责初始化数组元素内容(除非用带初始化的 new)。
class Holder {
int* data;
size_t size;
public:
Holder(size_t n) : size(n), data(new int[n]{}) { } // {} → 所有元素零初始化
};
-
data(new int[n]{}):C++11 起支持,{}触发值初始化(全部为 0) - 不要写
data = new int[n]在构造函数体里——这是错误模式 - 如果数组元素是类类型且无默认构造,
new MyClass[n]会编译失败;必须用new MyClass[n]{MyClass(arg), MyClass(arg), ...}或改用std::vector
类类型动态数组的坑:没有默认构造函数时怎么办
当数组元素是自定义类,且该类**只有带参构造、没有默认构造**时,new MyClass[n] 直接报错。必须显式提供每个元素的构造参数。
- 合法写法:
new MyClass[n]{MyClass(1), MyClass(2), MyClass(3)} - 非法写法:
new MyClass[n](编译器找不到默认构造) - 如果参数相同,可先构造一个临时对象再复制:
new MyClass[n]{MyClass(42), MyClass(42), MyClass(42)} - 更推荐方案:改用
std::vector<myclass></myclass>,它支持vector<myclass>(n, MyClass(arg))</myclass>这种带参批量构造
别忘了析构和移动语义
手动管理动态数组意味着你必须显式处理资源释放和所有权转移。光写构造函数远远不够。
- 必须提供析构函数:
delete[] data; - 必须禁用或实现拷贝构造/赋值(否则浅拷贝导致 double-free)
- C++11 起强烈建议添加移动构造和移动赋值,否则返回局部
Holder对象时会触发深拷贝 - 如果只是存数据,优先用
std::vector或std::unique_ptr<t></t>,它们自动处理这些细节
最易被忽略的是:初始化列表里的 new 表达式一旦抛异常(比如内存不足),已成功初始化的其他成员不会自动回滚——需要写异常安全的初始化逻辑,或者直接交给 RAII 容器处理。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











