c++ - 为什么 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!
}
够简单吧?那么汇编和 gcc 或者 clang是不-O3
一样的,和 比较长std::fill
,一般说明是真的下达了指令。
因此,除非我误解了,否则它确实很重要。
历史
原始 STL 的代码可以在这里找到。在版本 2 中,向量的内容已经被默认初始化。似乎委员会确认了已经存在的东西。
比较std::array
评论中有些人认为您绝对必须初始化向量的内容。但是,这确实是一个设计决定的证据是std::array
,相反,它不会默认初始化其内存。所以也许它更容易,或者更有意义,实现vector
和array
它们的方式,但相反的方式是可能的,两者都是。
解决方案
实际上,您可以避免这种情况。从cppreference中引用,例如resize
:
附加了其他默认插入的元素
讨论C++ 命名要求的页面: DefaultInsertable说(强调我的):
如果不需要值初始化,例如,如果对象是非类类型并且不需要清零,则可以通过提供自定义 Allocator::construct 来避免
最后,返回 Stack Overflow (!) 的链接显示了如何做到这一点(我没有详细分析此代码)。
当然,对于非 POD 类型,您确实希望默认构造新元素。否则,访问它们(甚至试图分配给它们)会导致 UB。
推荐阅读
- android - 应用程序关闭后如何“停止 Flutter 重建小部件”
- sql - 在复制 SQL Server 2014 下找不到 SQL Server 本地发布文件夹
- swift - 表格视图中的 Swift 全文搜索
- reactjs - 如何验证销售人员反应输入组件?
- java - 如何从 Primefaces 创建 UploadedFile.class 的测试对象?
- python - Python可以使用“return x if y”这一行吗?
- r - 使用 dplyr 添加值
- python - 如何使用这种类型的代码读取 txt 文件并将其转换为 xlsx 文件
- javascript - 编码挑战:元音索引
- javascript - 如何检查字符串是否包含Javascript中数组中的元素之一?