C++类添加自定义构造函数后使用new创建对象数组报错如何解决
报错原因
你添加自定义带参构造函数后,C++不会再为类自动生成无参默认构造函数,而new Foo[n]的语法要求Foo必须支持默认构造(会为数组内的n个元素依次调用无参构造),因此触发了匹配不到构造函数的报错,你的猜测是正确的。
修复方案
方案1:补充无参构造能力
最简单的改法,不需要改动原有make2D的逻辑,两种实现选一个即可:
- 给类显式添加无参构造函数:
class Foo{ public: Foo() = default; // C++11及以上可用,或者写空实现Foo(){} Foo(int a, int b){} // 其余代码不变 };
- 给现有带参构造的参数添加默认值:
Foo(int a = 0, int b = 0){}
方案2:使用定位new手动构造元素
如果业务不允许Foo存在无参构造,可以用定位new手动分配原始内存、逐个调用带参构造,不需要改用malloc:
注意:需要额外配套销毁逻辑,先手动调用每个对象的析构,再释放内存,避免内存泄漏和未定义行为。
#include <new> // 定位new需要的头文件 class Foo{ public: Foo(int a, int b){} static Foo ** make2D(int m, int n, int arg1, int arg2) { Foo **a = new Foo*[m]; for (int i = 0; i < m; i++) { // 先分配存储n个Foo的原始内存,不触发构造 a[i] = static_cast<Foo*>(operator new(sizeof(Foo) * n)); // 逐个调用带参构造初始化每个元素 for (int j = 0; j < n; j++) { new (&a[i][j]) Foo(arg1, arg2); } } return a; } static void destroy2D(Foo** arr, int m, int n) { for (int i = 0; i < m; i++) { // 逐个调用析构 for (int j = 0; j < n; j++) { arr[i][j].~Foo(); } // 释放原始内存 operator delete(arr[i]); } delete[] arr; } }; int main() { Foo ** x = Foo::make2D(2, 2, 10, 20); // 业务逻辑 Foo::destroy2D(x, 2, 2); return 0; }
不建议直接用malloc:malloc仅分配原始内存,不会处理C对象的构造逻辑,和上述operator new+定位new的实现逻辑没有本质区别,不符合C编码规范。
方案3:改用现代C++容器(更推荐)
放弃原生指针动态数组,使用std::vector,不需要手动管理内存,更安全:
#include <vector> class Foo{ public: Foo(int a, int b){} static std::vector<std::vector<Foo>> make2D(int m, int n, int arg1, int arg2) { return std::vector<std::vector<Foo>>(m, std::vector<Foo>(n, Foo(arg1, arg2))); } }; int main() { auto x = Foo::make2D(2, 2, 10, 20); // 直接使用即可,离开作用域自动释放内存 return 0; }
内容的提问来源于stack exchange,提问作者AlexSp3
相关产品推荐
相关产品推荐

