【问题标题】:Default-inserting into a vector isn't default initialization?默认插入向量不是默认初始化吗?
【发布时间】:2016-06-24 09:47:15
【问题描述】:

std::vector 的构造函数之一被规定为,强调我的:

explicit vector(size_type n, const Allocator& = Allocator());
效果:使用指定的分配器构造一个带有n默认插入元素的vector
需要: T 应将 DefaultInsertable 转换为 *this.
复杂性: 线性于 n

默认插入是否与默认初始化有关?在此代码上:

std::vector<char> v(66000);

gcc 5.2 优化生成:

  400d18:   bf d0 01 01 00          mov    $0x101d0,%edi
  400d1d:   48 83 c5 01             add    $0x1,%rbp
  400d21:   e8 1a fd ff ff          callq  400a40 <operator new(unsigned long)@plt>
  400d26:   31 f6                   xor    %esi,%esi
  400d28:   48 89 c3                mov    %rax,%rbx
  400d2b:   ba d0 01 01 00          mov    $0x101d0,%edx
  400d30:   48 89 c7                mov    %rax,%rdi
  400d33:   e8 38 fc ff ff          callq  400970 <memset@plt>

memset? 在这里做什么?我认为这应该简单地等同于new char[66000]... 也就是说,没有初始化。 clang 3.7 也会发出一个memset

为什么这里有memset?就标准而言,这是否正确?毕竟,如果我想要 66000 个值初始化字符,我已经有了这个构造函数:

std::vector<char> v(66000, '\0');

【问题讨论】:

  • 值初始化部分不是分配器的属性吗? IIRC 有一个答案(我认为来自 Howard Hinnant)展示了如何编写自定义分配器以避免初始化。
  • @Praetorian 没有线索。这不是我事前所期望的行为,也不是给定的措辞。因此问题。
  • 既然问题是关于为什么这里有 memset 也许是因为 C++ 是一个更好的 C,这意味着大多数 C++ STL 在其 libstc++ 库中使用 C
  • @Joel,什么? C++ 是更好的 C?
  • @SergeyA,来自 Bjarne Stroustrup 的书,没有被完全引用,但说 C++ 就像一个更好的 C。

标签: c++ c++11 vector


【解决方案1】:

这是正确的行为。见 23.2.1:

如果 X 的元素是通过计算表达式 allocator_traits&lt;A&gt;::construct(m, p) 来初始化的,则默认插入该元素

然后,allocator_traits&lt;A&gt;::construct 将调用a.construct(p, std::forward&lt;Args&gt;(args)...)。依次调用::new((void *)p) U(std::forward&lt;Args&gt;(args)...),后者实际上调用new(),后者进行值初始化。

结论:

memset() 是合适的。

结论#2

缺少自定义分配器,std::vector 不允许访问未初始化存储的选项。每个合法存在于向量中的对象都进行了值初始化。

【讨论】:

  • 那么“默认插入”一词是否等于“值初始化”?
猜你喜欢
  • 2013-01-17
  • 2012-11-29
  • 1970-01-01
  • 2014-12-29
  • 1970-01-01
  • 1970-01-01
  • 2017-11-21
  • 1970-01-01
相关资源
最近更新 更多