首页 > 解决方案 > 为什么 std::vector 初始化它的内容?

问题描述

假设我想创建一个vector并调用iota它:

std::vector<int> v(1000);
std::iota(begin(v),end(v),0);

向量实际上在构造函数中初始化为 0。问题与以下情况相同:

std::vector<int> v;
v.resize(1000);

我可以使用reserve,但我不能打电话iota。而且我看不到不进行零初始化的优雅方法(也许使用自定义分配器......?)。

为什么vector设计成这样?我知道 Stepanov 和合作者非常仔细地制作了 STL,并且几乎没有缺陷。但对我来说,它似乎与“你不为你不使用的东西付费”相冲突。这种设计的动机是什么?

回顾过去,是否有共识不应该那样做?(例如,无符号size_t用于size()人们似乎同意它应该是相同类型的情况,difference_type因为我们经常比较索引size())。

更多信息

表现

关于生成的代码的一些比较。编译器会优化 0-init 吗?使用时很难查看汇编程序,vector因为它做了很多事情,所以我尝试了以下代码:

int main() {
    int* v = new int[1000]; // clearer for reading assembly
    fill(v,v+1000,0);
    iota(v,v+1000,0);
    return v[999]; // do not optimize away!
}

结果在这里。然后删除_std::fill

够简单吧?那么汇编和 gcc 或者 clang是-O3一样的,和 比较长std::fill,一般说明是真的下达了指令。

因此,除非我误解了,否则它确实很重要。

历史

原始 STL 的代码可以在这里找到。在版本 2 中,向量的内容已经被默认初始化。似乎委员会确认了已经存在的东西。

比较std::array

评论中有些人认为您绝对必须初始化向量的内容。但是,这确实是一个设计决定的证据是std::array,相反,它不会默认初始化其内存。所以也许它更容易,或者更有意义,实现vectorarray它们的方式,但相反的方式是可能的,两者都是。

标签: c++stlstdstdvector

解决方案


实际上,您可以避免这种情况。从cppreference中引用,例如resize

附加了其他默认插入的元素

讨论C++ 命名要求的页面: DefaultInsertable说(强调我的):

如果不需要值初始化,例如,如果对象是非类类型并且不需要清零,则可以通过提供自定义 Allocator::construct 来避免

最后,返回 Stack Overflow (!) 的链接显示了如何做到这一点(我没有详细分析此代码)。

当然,对于非 POD 类型,您确实希望默认构造新元素。否则,访问它们(甚至试图分配给它们)会导致 UB。


推荐阅读