如何初始化由shared_ptr管理、需统一传递构造参数的对象数组
原生new T[N]语法不支持给动态数组的所有元素统一传递构造参数,仅支持默认构造或者花括号逐个指定初始值,因此你写的new car[100](1)不符合C++语法规范,会编译报错。
另外注意你示例代码里存在笔误:car构造函数的初始化列表写的是name(a),但你定义的成员变量是int val,这个问题也要同步修正。
以下是几种可行的实现方案:
方案1:用std::vector代替原生数组(最推荐,兼容性好、写法安全简洁)
std::vector本身支持构造时指定初始化值,你如果需要原生数组指针直接调用data()方法即可,完全兼容旧代码的使用习惯:
#include <map> #include <memory> #include <vector> struct car { car(int a) : val(a) {} int val; }; int main() { std::map<int, std::shared_ptr<std::vector<car>>> mp; // 第一个参数是元素数量,第二个是每个元素的构造参数 mp[0] = std::make_shared<std::vector<car>>(100, 1); // 访问元素和原生数组用法一致 int first_val = (*mp[0])[0].val; // 可以直接拿到原生指针 car* raw_ptr = mp[0]->data(); }
方案2:如果必须使用std::shared_ptr<car[]>类型(C++20及以上版本支持)
C++20对std::make_shared新增了数组重载,直接支持统一传递构造参数:
#include <map> #include <memory> struct car { car(int a) : val(a) {} int val; }; int main() { std::map<int, std::shared_ptr<car[]>> mp; // 第一个参数是数组长度,第二个是每个元素的构造参数 mp[0] = std::make_shared<car[]>(100, 1); }
方案3:C++11/17版本手动实现动态数组初始化
如果用的是旧标准,可以配合allocator手动完成内存分配、元素构造的逻辑:
#include <map> #include <memory> #include <algorithm> struct car { car(int a) : val(a) {} int val; }; int main() { std::map<int, std::shared_ptr<car[]>> mp; const size_t arr_size = 100; std::allocator<car> alloc; // 分配未初始化的内存 car* buf = alloc.allocate(arr_size); try { // 给所有元素执行构造,传入参数1 std::uninitialized_fill_n(buf, arr_size, 1); } catch (...) { // 构造异常时避免内存泄漏 alloc.deallocate(buf, arr_size); throw; } // 自定义删除器,释放时先析构元素再释放内存 mp[0] = std::shared_ptr<car[]>(buf, [arr_size, alloc](car* ptr) mutable { for (size_t i = 0; i < arr_size; ++i) { std::destroy_at(ptr + i); } alloc.deallocate(ptr, arr_size); }); }
内容的提问来源于stack exchange,提问作者James Franco
相关产品推荐
相关产品推荐

