【发布时间】:2014-02-05 18:37:58
【问题描述】:
假设我想构建一个矢量容器,unlike std::vector,允许未初始化的存储。容器的用法,比如vec <T>,大概是这样的:
-
用户明确指出向量应该像这样分配 N 个未初始化的元素:
vec <T> a(N, no_init); -
在数据已知的某个时刻,用户使用参数
args...显式初始化位置n的元素: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 或手动分配(例如使用operator new())等较低级别的解决方案在泄漏方面可能更具风险。我知道std::vector::emplace_back(),但这真的不是一回事。
【问题讨论】:
-
在调用
reserve之后,您想开发一个类似于std::vector的容器吗?来自this ref:“请求向量容量至少足以包含 n 个元素。” . -
听起来它根本不是你想要的向量。关联容器有什么问题?
-
@wesley.mesquita 仅部分。是的,我想要
reserve所做的分配,但我也希望数据完全可访问。例如。size()应该包括这些分配的元素。 -
破坏对我来说不是很清楚......这只有在容器知道哪些元素是真实的以及哪些是未初始化的情况下才有效。否则,正如你所说,你需要
is_trivially_destructible。 -
如果避免
vector::resize()和/或vector::vector(size_t)执行的值初始化足以解决您的问题,请查看this answer。
标签: c++ vector initialization typetraits destruction