我如何连接两个std::向量?


当前回答

我已经实现了这个函数,它连接任何数量的容器,从右值引用移动和复制

namespace internal {

// Implementation detail of Concatenate, appends to a pre-reserved vector, copying or moving if
// appropriate
template<typename Target, typename Head, typename... Tail>
void AppendNoReserve(Target* target, Head&& head, Tail&&... tail) {
    // Currently, require each homogenous inputs. If there is demand, we could probably implement a
    // version that outputs a vector whose value_type is the common_type of all the containers
    // passed to it, and call it ConvertingConcatenate.
    static_assert(
            std::is_same_v<
                    typename std::decay_t<Target>::value_type,
                    typename std::decay_t<Head>::value_type>,
            "Concatenate requires each container passed to it to have the same value_type");
    if constexpr (std::is_lvalue_reference_v<Head>) {
        std::copy(head.begin(), head.end(), std::back_inserter(*target));
    } else {
        std::move(head.begin(), head.end(), std::back_inserter(*target));
    }
    if constexpr (sizeof...(Tail) > 0) {
        AppendNoReserve(target, std::forward<Tail>(tail)...);
    }
}

template<typename Head, typename... Tail>
size_t TotalSize(const Head& head, const Tail&... tail) {
    if constexpr (sizeof...(Tail) > 0) {
        return head.size() + TotalSize(tail...);
    } else {
        return head.size();
    }
}

}  // namespace internal

/// Concatenate the provided containers into a single vector. Moves from rvalue references, copies
/// otherwise.
template<typename Head, typename... Tail>
auto Concatenate(Head&& head, Tail&&... tail) {
    size_t totalSize = internal::TotalSize(head, tail...);
    std::vector<typename std::decay_t<Head>::value_type> result;
    result.reserve(totalSize);
    internal::AppendNoReserve(&result, std::forward<Head>(head), std::forward<Tail>(tail)...);
    return result;
}

其他回答

如果你正在寻找的是在创建后将一个向量附加到另一个向量的方法,vector::insert是你最好的选择,因为已经回答了几次,例如:

vector<int> first = {13};
const vector<int> second = {42};

first.insert(first.end(), second.cbegin(), second.cend());

遗憾的是,没有办法构造一个const vector<int>,就像上面那样,你必须先构造然后插入。


如果你实际上是在寻找一个容器来保存这两个vector<int>s的连接,可能有更好的可用的东西给你,如果:

你的向量包含原语 包含的原语的大小为32位或更小 你需要一个const容器

如果以上都是正确的,我建议使用basic_string,它的char_type匹配vector中包含的原语的大小。你应该在你的代码中包含一个static_assert来验证这些大小保持一致:

static_assert(sizeof(char32_t) == sizeof(int));

有了这一点,你可以这样做:

const u32string concatenation = u32string(first.cbegin(), first.cend()) + u32string(second.cbegin(), second.cend());

要了解更多关于string和vector之间区别的信息,您可以查看这里:https://stackoverflow.com/a/35558008/2642059

有关此代码的实际示例,您可以在这里查看:http://ideone.com/7Iww3I

如果你正在使用c++ 11,并且希望移动元素而不仅仅是复制它们,你可以使用std::move_iterator和insert(或copy):

#include <vector>
#include <iostream>
#include <iterator>

int main(int argc, char** argv) {
  std::vector<int> dest{1,2,3,4,5};
  std::vector<int> src{6,7,8,9,10};

  // Move elements from src to dest.
  // src is left in undefined but safe-to-destruct state.
  dest.insert(
      dest.end(),
      std::make_move_iterator(src.begin()),
      std::make_move_iterator(src.end())
    );

  // Print out concatenated vector.
  std::copy(
      dest.begin(),
      dest.end(),
      std::ostream_iterator<int>(std::cout, "\n")
    );

  return 0;
}

对于int类型的例子来说,这并不会更有效,因为移动它们并不比复制它们更有效,但对于具有优化移动的数据结构,它可以避免复制不必要的状态:

#include <vector>
#include <iostream>
#include <iterator>

int main(int argc, char** argv) {
  std::vector<std::vector<int>> dest{{1,2,3,4,5}, {3,4}};
  std::vector<std::vector<int>> src{{6,7,8,9,10}};

  // Move elements from src to dest.
  // src is left in undefined but safe-to-destruct state.
  dest.insert(
      dest.end(),
      std::make_move_iterator(src.begin()),
      std::make_move_iterator(src.end())
    );

  return 0;
}

移动之后,src的元素处于未定义但可以安全销毁的状态,它之前的元素被直接转移到dest的新元素中。

或者你可以用:

std::copy(source.begin(), source.end(), std::back_inserter(destination));

如果两个向量不包含完全相同类型的内容,则此模式非常有用,因为您可以使用某些内容而不是std::back_inserter来从一种类型转换为另一种类型。

在一个std::vector中使用for循环连接两个std:: vectors。

    std::vector <int> v1 {1, 2, 3}; //declare vector1
    std::vector <int> v2 {4, 5}; //declare vector2
    std::vector <int> suma; //declare vector suma

    for(int i = 0; i < v1.size(); i++) //for loop 1
    {
         suma.push_back(v1[i]);
    }

    for(int i = 0; i< v2.size(); i++) //for loop 2
    {
         suma.push_back(v2[i]);
    }

    for(int i = 0; i < suma.size(); i++) //for loop 3-output
    {
         std::cout << suma[i];
    }

将这个添加到头文件中:

template <typename T> vector<T> concat(vector<T> &a, vector<T> &b) {
    vector<T> ret = vector<T>();
    copy(a.begin(), a.end(), back_inserter(ret));
    copy(b.begin(), b.end(), back_inserter(ret));
    return ret;
}

然后这样用:

vector<int> a = vector<int>();
vector<int> b = vector<int>();

a.push_back(1);
a.push_back(2);
b.push_back(62);

vector<int> r = concat(a, b);

R将包含[1,2,62]