new表达式直接传参调用构造函数,语法同栈上构造;支持所有可访问构造函数,explicit不限制;异常时自动释放内存;推荐用make_unique/make_shared替代裸new;数组new不支持传参。

new 表达式里直接传参,语法和栈上构造一致
动态创建对象时传构造参数,就是把 new 后面的类型名当成构造函数调用来看待。比如类 A 有 A(int, std::string) 构造函数,那直接写 new A(42, "hello") 就行——不是先 new 再调构造,而是 new 的过程本身就触发带参构造。
常见错误是试图分开写:A* p = new A(); p->A(42, "hello"); ——这会编译失败,A(42, "hello") 不是可调用的成员函数,构造函数不能显式重调。
- 支持所有可访问的构造函数:含默认参数、委托构造、初始化列表等
- 如果构造函数是 explicit,
new调用不受影响,explicit 只约束隐式转换,不约束直接调用 - 异常安全要注意:若构造函数抛异常,
new会自动释放已分配的内存,不会造成泄漏
使用 std::make_unique 或 std::make_shared 更安全
裸 new 容易出问题,尤其在表达式复杂或涉及多个动态分配时(比如 func(new A(1), new B(2)),若其中一个 new 成功另一个失败,前者就泄漏了)。现代 C++ 推荐用 std::make_unique 和 std::make_shared。
它们的参数传递方式和 new 完全一样,只是包了一层:
立即学习“C++免费学习笔记(深入)”;
auto ptr1 = std::make_unique<A>(42, "hello"); auto ptr2 = std::make_shared<B>(3.14, true);
- 参数完美转发:支持移动语义、引用折叠,能正确传递临时对象和左值
- 异常安全:内部用
new,但保证“要么全成功,要么不泄漏” -
std::make_shared还有内存优化:控制块和对象内存通常一次分配,比分别 new 控制块 + new 对象更高效
数组 new 无法传非平凡构造参数
new A[10] 这种数组形式,只能调用默认构造函数(或无参构造函数),不支持传参。C++ 标准禁止写 new A[10](1, "x"),编译器会报错类似 error: expected primary-expression before '[' token。
如果真需要带参构造的数组,得手动循环:
std::vector<A> vec;
vec.reserve(10);
for (int i = 0; i < 10; ++i) {
vec.emplace_back(i, "item");
}
- 优先用
std::vector+emplace_back:语义清晰、自动管理、支持任意构造参数 - 若必须用裸指针数组,只能配合 placement new 手动管理内存,但极易出错,不推荐
- 注意:即使类有默认构造函数,
new A[10]也会调用它 10 次;没有默认构造则编译失败
自定义分配器下传参逻辑不变,但需确保构造函数可访问
用带分配器的 new(如 new (my_allocator) A(1, 2))时,参数传递方式不变,但有两个隐藏前提:
- 分配器返回的内存地址必须对齐到
A的要求,否则A(1, 2)的 placement new 可能触发未定义行为 - 如果
A的构造函数是 private,而分配器代码不在A的友元范围内,就会编译失败:不是参数问题,是访问权限问题 - 自定义分配器本身不参与构造逻辑,它只管内存;构造仍由编译器生成的代码完成
实际项目中,除非做高性能内存池或嵌入式场景,否则极少需要手写带分配器的 new 表达式——这时候往往已经绕不开对齐、生命周期和异常处理的细节了。


















