假设我想构建一个向量容器,与 std::vector 不同,它允许未初始化的存储。容器的用法,比如说vec <T>
,大概是这样的:
用户明确指出向量应该分配 N 个未初始化的元素,如下所示:
vec <T> a(N, no_init);
在数据已知的某个时刻,用户
n
使用参数显式初始化位置处的元素args...
:a.init(n, args...);
或者,等效地,手动构造元素:
new (&a[n]) T(args...);
其他操作可能会更大规模地初始化或复制(如
std::uninitialized_copy
),但这只是为了方便;基本的底层操作是相同的。完成某些任务后,向量可能会留下一些已初始化的元素,而另一些则没有。该向量不包含任何额外信息,因此最终,在释放内存之前,它要么销毁所有元素,要么仅根据
T
.
我很确定这是可以做到的,只是我不确定后果。自然地,我们希望这个结构对所有类型都是安全的,T
假设用户在构造它之前没有尝试使用未初始化的元素。这听起来像是一个强有力的假设,但仅访问向量范围内的元素并没有太大的不同,而且它很常见。
所以我的问题是:
对于哪些类型,允许这种未初始化的操作是安全的
vec <T> a(no_init)
?我想is_pod
会没问题,而且很可能is_trivial
也是如此。我不想施加不必要的限制。应该始终执行销毁还是仅针对某些类型执行销毁?与上面相同的约束可以吗?怎么样
is_trivially_destructible
?这个想法是破坏尚未构造的元素,反之亦然(不破坏构造的元素)应该没有害处。除了给用户带来更多责任的明显风险之外,这种尝试是否存在重大缺陷?
重点是,当用户确实需要此类功能以提高性能时,较低级别的解决方案std::get_temporary_buffer
(如手动分配(例如 with operator new()
))在泄漏方面可能更具风险。我知道,std::vector::emplace_back()
但这真的不是一回事。