如果之前已经回答过这个问题,我深表歉意,我只是无法在最后找到问题的确切答案。
这是一个简化版本的集合。
template <typename T>
struct my_collection
{
T* buffer_start = nullptr;
std::size_t capacity;
std::size_t size;
T* buffer_end = nullptr;
// definition of reference, iterators, value_type etc are ommited.
my_collection(std::size_t capacity) : capacity{ capacity }, buffer_end{ 0 }
{
auto memory = ::operator new(capacity * sizeof(T), std::align_val_t{ alignof(T) });
// I am not sure I am using std::align_val_t correctly here and feel free to correct me,
// but I assume that idea is clear
buffer_start = static_cast<T*>(memory);
// I think that memory variable can be eliminated, and everything can be in one line
buffer_end = buffer_start;
}
// assume that insertions and removals occur at the end for simplicity and omit move semantics
// for simplicity and assume copy construction is legal
void insert(const T& x)
{
// overflow check is omitted - assume that size < capacity
new (buffer_end) T{ x };
++size;
++buffer_end;
// buffer_start = std::launder(buffer_start)
}
void remove_last()
{
// omit checking for empty etc
--buffer_end;
--size;
// Assumption that destructor exists for simplicity - otherwise use destroy_at or implement
// custom destruction
std::launder(buffer_start + size)->~T();
// is this even legal or also leads to UB?
// will these buffer_start = std::launder(buffer_start);
}
// const version is omitted
T& operator[](std::size_t index)
{
return *(std::launder(T + index));
// if I use buffer_start = std::launder(buffer_start) after every insertion, is std::launder still needed?
}
~my_collection()
{
while (size > 0) remove_last();
::operator delete(static_cast<void*>(buffer_start), capacity*sizeof(T), std::align_val_t{ alignof(T) });
// is it safe, or there are more unexpected quirks?
}
};
这是我的问题。(总结评论中出现的问题)。
- 分配内存时,分配它并保留
T*
指针是否足够buffer_start
?还是仍然需要原始内存指针?(我没有看到原因,但直到几天前我才知道reintpret_cast<T*>
会导致 UB)。 - 如果我想访问集合中的元素,我应该使用
std::launder(reinterpret_cast<T*>(buffer_start + i))
,因为我已经放置了新分配或std::launder(buffer_start)
为我解决了这个问题(它甚至有帮助,或者只是没有效果),如果我记得每次删除一个元素时都执行它收藏?(删除元素时甚至需要它吗?)。 delete
在析构函数中使用正确吗?- 使用构造元素是否安全,
new(buffer_start+size)
或者我实际上需要原始内存指针?