无法拷贝、移动且无默认构造的结构体堆分配方案咨询
问题描述
我定义了一个既无法拷贝、移动,也没有默认构造函数的结构体:
struct Data { int a; Data(const Data&) = delete; Data& operator=(const Data&) = delete; Data(Data&&) = delete; Data& operator=(Data&&) = delete; Data(int i): a{i} {} };
我希望在堆上分配该结构体的数组,并使用同一个构造函数完成所有实例的初始化。目前我通过以下方式实现:
Data* ppd = (Data*)::operator new(10 * sizeof(Data)); for (auto p = ppd; p < ppd + 10; ++p) new(p) Data{45};
但我对这个实现并不满意,请问有没有更具表达性的实现方法?
解决方案
由于Data结构体禁用了拷贝、移动构造,且没有默认构造函数,无法通过批量拷贝的方式初始化数组,核心逻辑仍需基于分配原始内存+逐个构造,但可以借助C++标准库组件让代码更具表达性和规范性:
方法一:使用std::allocator(C++11及以上)
std::allocator是标准库提供的内存管理工具,封装了内存分配/释放和对象构造/销毁的细节,代码风格更符合现代C++:
#include <memory> // 创建分配器实例 std::allocator<Data> alloc; // 分配能容纳10个Data对象的内存 Data* ppd = alloc.allocate(10); // 逐个构造Data对象,传入构造参数45 for (std::size_t i = 0; i < 10; ++i) { alloc.construct(ppd + i, 45); } // 注意:后续需要用allocator销毁对象并释放内存 // for (std::size_t i = 0; i < 10; ++i) { // alloc.destroy(ppd + i); // } // alloc.deallocate(ppd, 10);
方法二:使用std::construct_at配合范围迭代(C++20及以上)
C++20引入的std::construct_at可以替代placement new,配合范围库的迭代器让代码更简洁直观:
#include <memory> #include <ranges> // 分配原始内存 Data* ppd = static_cast<Data*>(::operator new(10 * sizeof(Data))); // 遍历指针范围,逐个构造对象 auto ptr_range = std::ranges::subrange(ppd, ppd + 10); for (auto p : ptr_range) { std::construct_at(p, 45); } // 后续销毁和释放内存示例 // for (auto p : ptr_range) { // std::destroy_at(p); // } // ::operator delete(ppd);
这些方案本质上和你原本的实现逻辑一致,但通过标准库组件提升了代码的可读性和表达性,同时避免了裸指针操作的一些潜在问题。
内容的提问来源于stack exchange,提问作者MaPo
相关产品推荐
相关产品推荐

