【发布时间】:2021-07-08 06:16:08
【问题描述】:
我正在尝试构建一个类来管理 std::vector
我遇到的问题是构建如下图的向量会导致非连续分配的对象:
std::vector<T*> objects{};
for (size_t i = 0; i < n; i++) objects.push_back(new T());
这是因为new T() 的两次连续执行不必在内存中产生连续的对象。所以解决方案是改用new[] 运算符,这让我接受了这个实现:
template<class T>
class HeapVector
{
private:
std::vector<T*> elems_{};
const size_t BUFFER_SIZE_{}; // Buffer size
size_t idx_{}; // Index controlling the index local to the buffer.
T * buffer_ = nullptr; // Buffer
public:
HeapVector() = default;
HeapVector(const size_t BUFFER_SIZE = 256) : BUFFER_SIZE_(BUFFER_SIZE) {};
void emplace_back() // TODO: Should pass constructor parameters or even a constructor
{
if (!(elems_.size() % BUFFER_SIZE_))
{
idx_ = 0;
buffer_ = new T[BUFFER_SIZE_];
elems_.reserve(elems_.size() + BUFFER_SIZE_);
}
// TODO: Object constructor. Must initialize buffer_[idx]
// createElement(buffer_[idx], parameters...);
elems_.push_back(buffer_ + idx_++);
}
};
通过执行new T[BUFFER_SIZE_],我获得了一个指针,该指针指向使用默认构造函数构建的连续分配的 BUFFER_SIZE_ 元素数组的第一个元素。
我想要实现的是,在这个分配完成后,用所需的参数/另一个构造函数初始化这个对象(参见 TODOs)。另外,我想避免使用复制构造函数。
鉴于我希望此类成为模板类,实现这一目标的最通用方法是什么?
【问题讨论】:
-
听起来你可能想使用placement new。
-
"指向必须在堆中连续分配的对象的指针。" - 那么为什么要存储指针呢?为什么不
std::vector<T>? -
我不明白为什么您需要创建更多对象只是因为您将它们直接存储在向量中而不是存储指向每个对象的指针。
-
"我不想混合使用
std::vector<T>和std::vector<T*>" - 为什么?带有T的那个将是拥有它的那个,其余的可以存储T*。只要拥有的vector不需要重新分配它就应该是安全的,如果它必须重新分配,则需要重新创建指针向量。 -
补充@TedLyngmo 的评论:此外,如果您使用索引而不是指针,那么使用向量重新分配也是安全的。
标签: c++ memory heap-memory