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 完全一样,只是包了一层:
auto ptr1 = std::make_unique<a>(42, "hello"); auto ptr2 = std::make_shared<b>(3.14, true); </b></a>
- 参数完美转发:支持移动语义、引用折叠,能正确传递临时对象和左值
- 异常安全:内部用
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 <ul> <li>优先用 <code>std::vector</code> + <code>emplace_back</code>:语义清晰、自动管理、支持任意构造参数</li> <li>若必须用裸指针数组,只能配合 placement new 手动管理内存,但极易出错,不推荐</li> <li>注意:即使类有默认构造函数,<code>new A[10]</code> 也会调用它 10 次;没有默认构造则编译失败</li> </ul> <h3>自定义分配器下传参逻辑不变,但需确保构造函数可访问</h3> <p>用带分配器的 <code>new</code>(如 <code>new (my_allocator) A(1, 2)</code>)时,参数传递方式不变,但有两个隐藏前提:</p> <ul> <li>分配器返回的内存地址必须对齐到 <code>A</code> 的要求,否则 <code>A(1, 2)</code> 的 placement new 可能触发未定义行为</li> <li>如果 <code>A</code> 的构造函数是 private,而分配器代码不在 <code>A</code> 的友元范围内,就会编译失败:不是参数问题,是访问权限问题</li> <li>自定义分配器本身不参与构造逻辑,它只管内存;构造仍由编译器生成的代码完成</li> </ul> <p>实际项目中,除非做高性能内存池或嵌入式场景,否则极少需要手写带分配器的 new 表达式——这时候往往已经绕不开对齐、生命周期和异常处理的细节了。</p></a>
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











