【问题标题】:Reserve a vector of reference_wrapper objects, how it is possible?预留一个reference_wrapper对象的向量,怎么可能?
【发布时间】:2016-09-15 02:54:26
【问题描述】:

std::reference_wrapper 不是默认可构造的。所以我什么都写不出来:

std::vector<std::reference_wrapper<int>> vec(10);
std::array<std::reference_wrapper<int>, 3> arr;

但是,令我惊讶的是,您可以调用std::reference_wrapper 对象向量的std::vector::reserve 成员函数并有效地更改其容量。

std::vector<std::reference_wrapper<int>> vec;  
vec.reserve(10);

Live Demo

std::reference_wrapper 没有默认构造函数,这怎么可能?

【问题讨论】:

  • reserve() 不创建对象。如果你改用resize() 怎么办?
  • 您在问题中写的内容几乎与您的问题无关......
  • @Barry 随时编辑...
  • @Barry 或提出改进建议...
  • @101010 当然可以。你的问题是真的:为什么我可以reserve 一个vector&lt;reference_wrapper&lt;T&gt;&gt;。第一部分是关于参考的,但您没有任何参考。第二部分解释了 reference_wrapper 是什么 - 但这也不是真正相关的,因为您的问题对于保留 struct foo { foo(int ) }; 的向量同样有效

标签: c++ c++11 vector c++14 reference-wrapper


【解决方案1】:

reserve 不构建任何新元素。最坏的情况是它只会移动/复制已经创建的。

【讨论】:

  • 添加新的 N 个单元时不会引起重新分配
  • 我改写了这句话
【解决方案2】:

可以参考SGI STL实现

在stl_vector.h中:

void reserve(size_type __n) {
    if (capacity() < __n) {
      const size_type __old_size = size();
      iterator __tmp = _M_allocate_and_copy(__n, _M_start, _M_finish);
      destroy(_M_start, _M_finish);
      _M_deallocate(_M_start, _M_end_of_storage - _M_start);
      _M_start = __tmp;
      _M_finish = __tmp + __old_size;
      _M_end_of_storage = _M_start + __n;
    }
  }

void resize(size_type __new_size) { resize(__new_size, _Tp()); }

reserve 不会创建新元素,但是 resize 会。

【讨论】:

  • 您知道 SGI STL 的年龄吗?
  • @sleeptightpupper 因为它老了,所以很容易阅读,而且我相信 STL 的基本思想并没有太大变化。
  • 这只是规范的一个(和旧的)实现。我相信在这里引用此代码实现的规范会更合适(并且更普遍适用),特别是因为 OP 使用您在此处发布的实现的几率很低。
  • @jaggedSpire 这个实现没有实现 C++ std:C++ std 是基于这个实现的!虽然它不是权威的,但它是理解许多std 类型所做的最简单和最容易阅读的方法之一,这一事实在其专栏中是一大优势。可能存在并且将会存在差异,但在许多情况下,易于阅读可以胜过精确的正确性。
  • @Yakk 哦,太好了!我不知道。
【解决方案3】:

vector::reserve(N) 只是为N 元素预先分配存储容量。您使用的向量构造函数是“默认填充”构造函数 - 它创建 N default-constructor 元素并将它们插入容器中。

例如

vector<T> v;
v.reserve(N);
assert(0 == v.size());
assert(N >= v.capacity());

vector<T> v(N);
assert(N == v.size());
assert(N >= v.capacity());

根据 C++17 工作草案的 23.3.6.3.p2 [vector.capacity],vector::reserve() 只要求 TMoveInsertable*this。有问题的构造函数在 23.3.6.2.p3 [vector.cons] 中指定,并要求 T 应为 DefaultInsertable*this

reference_wrapper&lt;&gt;MoveInsertable 但不是 DefaultInsertable (如您所述,它不能默认构造)。有关这些概念的确切定义,请参阅 23.2.1.p15 [containers.requirements.general]。

【讨论】:

    猜你喜欢
    • 2019-01-09
    • 2018-03-31
    • 1970-01-01
    • 1970-01-01
    • 2011-12-19
    • 2023-03-06
    • 1970-01-01
    • 1970-01-01
    • 2012-02-09
    相关资源
    最近更新 更多