17

C++11 给了我们很好的std::array,这需要在编译时知道大小:

std::array<int, 3> myarray = {1, 2, 3};

现在,我碰巧有一些旧的short*缓冲区要包装,它们的大小仅在运行时才知道(当然是)。

C++14 将定义std::dynarray以涵盖这种情况,但dynarray在 GCC 4.7 和 Clang 3.2 中尚不可用。

那么,有没有人知道一个与(在效率方面)相当std::array但不需要在编译时指定大小的容器?我怀疑 Boost 已经为我准备好了一些东西,尽管我找不到任何东西。

4

6 回答 6

16

我认为std::vector这是您在可用之前正在寻找的东西dynarray。只需使用分配构造函数,否则reserve您将避免重新分配开销。

于 2013-06-25T17:39:47.017 回答
9

std::unique_ptr<short[]>(new short[n])如果您不需要std::dynarray<T>::at(). 你甚至可以使用初始化列表:

#include <iostream>
#include <memory>

int main(int argc, char** argv) {
  const size_t n = 3;
  std::unique_ptr<short[]> myarray(new short[n]{ 1, 2, 3 });
  for (size_t i = 0; i < n; ++i)
    std::cout << myarray[i] << '\n';
}
于 2013-06-25T18:06:59.583 回答
5

你可以(ab)使用std::valarray<short>.

int main() {
    short* raw_array = (short*) malloc(12 * sizeof(short));
    size_t length = 12;
    for (size_t i = 0; i < length; ++ i) {
        raw_array[i] = (short) i;
    }

    // ...

    std::valarray<short> dyn_array (raw_array, length);
    for (short elem : dyn_array) {
        std::cout << elem << std::endl;
    }

    // ...

    free(raw_array);
}

valarray支持 a 的大多数功能dynarray,除了:

  • 分配器
  • 反向迭代器
  • .at()
  • .data()

请注意,标准(从 n3690 开始)不要求valarray存储是连续的,尽管没有理由不这样做:)。

(对于一些实现细节,在 libstdc++ 中它被实现为(长度,数据)对,而在 libc++ 中,它被实现为(开始,结束)。)

于 2013-06-25T18:00:19.803 回答
4

缓冲区和大小,加上一些基本方法,可以满足您的大部分需求。

很多样板,但像这样:

template<typename T>
struct fixed_buffer {
  typedef       T                               value_type;
  typedef       T&                              reference;
  typedef const T&                              const_reference;
  typedef       T*                              iterator;
  typedef const T*                              const_iterator;
  typedef std::reverse_iterator<iterator>       reverse_iterator;
  typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
  typedef size_t                                size_type;
  typedef ptrdiff_t                             difference_type;

  std::size_t length;
  std::unique_ptr<T[]> buffer;

  std::size_t size() const { return length; }

  iterator begin() { return data(); }
  const_iterator begin() const { return data(); }
  const_iterator cbegin() const { return data(); }
  iterator end() { return data()+size(); }
  const_iterator end() const { return data()+size(); }
  const_iterator cend() const { return data()+size(); }

  reverse_iterator rbegin() { return {end()}; }
  const_reverse_iterator rbegin() const { return {end()}; }
  const_reverse_iterator crbegin() const { return {end()}; }
  reverse_iterator rend() { return {begin()}; }
  const_reverse_iterator rend() const { return {begin()}; }
  const_reverse_iterator crend() const { return {begin()}; }

  T& front() { return *begin(); }
  T const& front() const { return *begin(); }
  T& back() { return *(begin()+size()-1); }
  T const& back() const { return *(begin()+size()-1); }
  T* data() { return buffer.get(); }
  T const* data() const { return buffer.get(); }
  T& operator[]( std::size_t i ) { return data()[i]; }
  T const& operator[]( std::size_t i ) const { return data()[i]; }
  fixed_buffer& operator=(fixed_buffer &&) = default;
  fixed_buffer(fixed_buffer &&) = default;

  explicit fixed_buffer(std::size_t N):length(N), buffer( new T[length] ) {}
  fixed_buffer():length(0), buffer() {}

  fixed_buffer(fixed_buffer const& o):length(o.N), buffer( new T[length] )
  {
    std::copy( o.begin(), o.end(), begin() );
  }
  fixed_buffer& operator=(fixed_buffer const& o)
  {
    std::unique_ptr<T[]> tmp( new T[o.length] );
    std::copy( o.begin(), o.end(), tmp.get() );
    length = o.length;
    buffer = std::move(tmp);
    return *this;
  }
};

at()丢失了,分配器也丢失了。

operator=与提案不同dyn_array——提案块operator=,我给它价值语义。一些方法效率较低(如copy构造)。我允许空fixed_buffer

这可能会阻止能够使用堆栈来存储 a dyn_array,这可能是它不允许它的原因。operator=如果您想要更接近 dyn_array 的行为,只需删除我的微不足道的构造函数。

于 2013-06-25T19:37:25.600 回答
0

C++14 还添加了可变长度数组,类似于 C99 中的数组,一些编译器已经支持:

void foo(int n) {
  int data[n];
  // ...
}

它不是一个容器,因为它不支持begin()等等end(),但可能是一个可行的解决方案。

于 2013-06-27T13:22:57.657 回答
0

dynarray在没有堆栈分配组件的情况下很容易实现自己——这显然在C++14 之前是不可能的——所以我只是滚动了一个反向dynarray 反向端口(前向端口?)作为我的库的一部分并开始使用它自从。到目前为止,在没有任何“内布拉斯加州无效”条款的情况下在 C++03 中工作,因为它并不绝对依赖于任何 C++11 特定的功能,并且
当 C++1y/2zdynarray出现时,它很整洁我的代码在很大程度上仍然兼容。

(这也是许多明显的“为什么 C++ 不早点拥有这个?”的事情之一,所以拥有它是件好事)。

这是在我了解到显然 C++1y-dynarray和 C++1y-runtime-size-arrays 是完全相同的提议之前(一个只是另一个的语法糖),而不是我第一次提出的两个不同但互补的提议想法。因此,如果我现在必须解决同样的问题,我可能会切换到基于@Yakk 解决方案的正确性。

于 2013-11-28T01:21:49.480 回答