std :: vector :: reserve是否保证在这种情况下实现不会使迭代器失效?

时间:2017-09-09 16:23:42

标签: c++ c++11 language-lawyer stdvector

这是一个打算执行的功能:

a)接受int

的向量

b)对于输入向量中的每个int,追加此int的反函数

前提条件:无

后置条件:返回向量的大小()是2 *输入向量的大小。

请注意,矢量已就地修改。

问题:

这个函数是否严格定义了变换期间迭代器失效的行为?

加成:

是否有更好/更简洁/更健壮的方式来编写它?

代码:

{{1}}

2 个答案:

答案 0 :(得分:14)

只要不超过预分配容量,就不会发生重新分配,也不会使引用矢量项的引用或迭代器失效。但是,由于end()返回的迭代器未引用任何向量项,因此它可能仍会失效。

  

23.3.11.3载体容量 [vector.capacity]

     
      
  1. ...在调用reserve()之后发生的插入过程中不会发生重新分配,直到插入使向量的大小大于capacity()   

...

  

23.3.11.5向量修饰语 [vector.modifiers]

     
      
  1. ...如果没有重新分配,插入点之前的所有迭代器和引用仍然有效。
  2.   

答案 1 :(得分:4)

关于迭代器失效规则的部分已经被涵盖了,所以我将借此机会谦虚地质疑是否需要使用所有这些机制(以其微妙的规则)来处理这样一个微不足道的问题。你也可以认为这是对

的刺激
  

加成:

     

是否有更好/更简洁/更健壮的方式来编写它?

问题的一部分。

老实说,我完全用 Status({ input, meta: {touched, error}, ...custom }) { const reduxFormOnChange = input.onChange; // the signature for this onChange is specific to // semantic-ui Select const semanticSelectOnChange = (maybe, wrong, order, or, irrelevant) => { // here we make the translation // so that the Redux form onChange gets // called correctly. // (NOTE: this is an example, not actual code suggestion) reduxFormOnChange(or, maybe); }; return ( <Form.Field control={Select} name="Status" label="Status" options={status} placeholder="Status" {...input} {...custom} onChange={ semanticSelectOnChange } /> ); } 循环的先进技术来回避这个问题。 KISS

for

并非所有内容都必须在深层的STL算法中进行混淆。这个更短,IMO更具可读性,并避免了关于迭代器失效的麻烦。

此外,除非编译器自上次检查以来已经获得了额外的智能,否则这要快得多,因为避免了std::vector<int> append_negatives(std::vector<int> v) { size_t sz = v.size(); v.resize(sz*2); for(size_t i = 0; i < sz; ++i) v[i+sz] = -v[i]; return v; } 的所有开销(检查容量是否足够以及每次迭代时的增量大小),这将被替换直接指针访问(一个汇编指令);纤细而简单的环体为自动展开提供了更好的机会。我希望编译速度更快,因为我们避免实例化一堆模板。

请注意,即使使用push_back benemoth,也可以获得速度优势/无失效头痛:

transform

但我没有看到这种过于冗长的代码优于普通std::vector<int> append_negatives(std::vector<int> v) { size_t sz = v.size(); v.resize(sz * 2); auto beg = begin(v); std::transform(beg, beg + sz, beg + sz, [](int x) { return -x; }); return v; } 循环的任何优势,除非你通过&#34; cool&#34;您可以使用C ++功能来挤入代码。

@MikeMB询问默认构造成本高昂的类型;在这种情况下,明确的for很好:

push_back

如果原始帖子中的std::vector<int> append_negatives(std::vector<int> v) { size_t sz = v.size(); v.reserve(sz*2); // optional for(size_t i = 0; i < sz; ++i) v.push_back(-v[i]); return v; } 有效,您还可以使用基于范围的for循环:

transform

方式在眼睛上比基于转换的解决方案更好,但我在评论中看到,对于结束迭代器失效仍然没有达成共识,所以这只是无效。