如何将 std::array 元素附加或插入 std::vector?

ZzX*_*SZD 4 c++ stdvector stdarray c++17

我对 C++ 比较陌生,我尝试做一些研究,但是在网上搜索时,我主要遇到的是 C 数组而不是std::array. 将 std::array 元素附加到 std::vector 并将std::array元素插入到 a中的最有效方法是std::vector什么?我应该使用 STL 函数,例如std::copy? 我目前正在使用 C++17,MinGW64。

StP*_*ere 9

要将现有数组(或一般其他范围)的元素附加到向量,您只需将向量的插入重载用于迭代器范围:

   vector<int> vec{1, 2, 3};
   array<int, 3> arr{4, 5, 6};
   // arr could be some other container or bare array as well, for ex.:
   // int arr[] = {4, 5, 6};
   // vector<int> arr {4, 5, 6};
   // list<int> arr {4, 5, 6};
   // ...
   
   vec.insert(vec.end(), begin(arr), end(arr));  // insert at vec.end() = append
  //or  vec.insert(vec.end(), arr.begin(), arr.end());  // insert at vec.end() = append
Run Code Online (Sandbox Code Playgroud)

请注意,如果您有其他类型而不是int复制成本高昂的类型,并且您从源数组中移动元素,则可以使用 move_iterator,例如。

vec.insert(vec.end(), move_iterator(arr.begin()), move_iterator(arr.end()));
Run Code Online (Sandbox Code Playgroud)

对于一般范围的操作容器成员函数首选,而不是来自<algorithm>标题的同名函数。

因此,例如在这种情况下,vec.insert将立即插入范围,而不是使用了std::insert将元素一一插入的位置。

这在 Scott Meyers Effective STL 中有很好的解释。

居住


lub*_*bgr 7

“附加”值可能意味着两件事 - 您要么想要复制/复制有问题的元素,要么在源容器中不需要它们,也可能将它们移动到目标容器中。此外,区分构建时插入和附加到现有的、已经构建的容器是有意义的:如果可以,总是使用它应该拥有的元素构建一个容器。

  1. std::array元素复制附加到已构造的std::vector:

    std::vector<T> dest;
    std::array<T, N> source;
    
    // ...
    
    dest.insert(dest.end(), source.cbegin(), source.cend());
    
    Run Code Online (Sandbox Code Playgroud)
  2. std::array元素移动到已构造的std::vector.

    std::vector<T> dest;
    std::array<T, N> source;
    
    // ...
    
    dest.insert(dest.end(), std::move_iterator(source.begin()),
                std::move_iterator(source.end()));
    
    Run Code Online (Sandbox Code Playgroud)
  3. std::array元素复制到std::vectorat 构造中:

    std::array<T, N> source;
    
    // ...
    
    std::vector<T> dest(source.cbegin(), source.cend());
    
    Run Code Online (Sandbox Code Playgroud)
  4. std::array元素移动到std::vectorat 构造中:

    std::array<T, N> source;
    
    // ...
    
    std::vector<T> dest(std::move_iterator(source.begin()),
                        std::move_iterator(source.cend()));
    
    Run Code Online (Sandbox Code Playgroud)

在谈论插入到中间时,这里没有什么可添加的——唯一显着的区别是它总是效率较低,因为目标中的其余元素std::vector将是移动构造的(即 O(N))。

另请注意,对于附加元素,有std::movestd::copy来自<algorithm>标题(std::copy可以与std::move_iterators一起使用)。但是,这些不能像直接调用 那样有效std::vector::insert,因为前者对迭代器抽象进行操作并在不知道目标的存储细节的情况下一次处理复制/移动一个元素(这可能导致多次缓冲区大小调整) ,而后者是一个std::vector成员函数,只会调整缓冲区大小一次(如果需要)。