Answers:
AB.reserve( A.size() + B.size() ); // preallocate memory
AB.insert( AB.end(), A.begin(), A.end() );
AB.insert( AB.end(), B.begin(), B.end() );
这正是成员函数std::vector::insert
的用途
std::vector<int> AB = A;
AB.insert(AB.end(), B.begin(), B.end());
insert
于随机访问迭代器并预先预留,我不会感到惊讶。
distance
复杂度为O(1))。尽管如此,insert
当您经常通过预先计划可以做得更好时,仍然需要牢记性能保证。
size < capacity
大多数情况下,分支预测可能会导致非重分配分支的指令进入指令管道,从而将分支引起的等待时间降至最低,但迭代次数较少。这假设一个好的向量实现,再加上CPU指令流水线和[好的]分支预测,但是对于现代工具链和台式机来说,这是相当可靠的假设。虽然不了解智能手机..
取决于您是否真的需要物理连接这两个向量,还是要出于迭代的目的给出连接的外观。boost :: join函数
http://www.boost.org/doc/libs/1_43_0/libs/range/doc/html/range/reference/utilities/join.html
会给你这个。
std::vector<int> v0;
v0.push_back(1);
v0.push_back(2);
v0.push_back(3);
std::vector<int> v1;
v1.push_back(4);
v1.push_back(5);
v1.push_back(6);
...
BOOST_FOREACH(const int & i, boost::join(v0, v1)){
cout << i << endl;
}
应该给你
1
2
3
4
5
6
注意boost :: join不会将两个向量复制到新容器中,而是会生成一对覆盖两个容器范围的迭代器(范围)。将有一些性能开销,但可能比首先将所有数据复制到新容器要少。
根据Kiril V. Lyadvinsky的答案,我制作了一个新版本。此代码段使用模板和重载。有了它,您可以编写vector3 = vector1 + vector2
和vector4 += vector3
。希望能有所帮助。
template <typename T>
std::vector<T> operator+(const std::vector<T> &A, const std::vector<T> &B)
{
std::vector<T> AB;
AB.reserve(A.size() + B.size()); // preallocate memory
AB.insert(AB.end(), A.begin(), A.end()); // add A;
AB.insert(AB.end(), B.begin(), B.end()); // add B;
return AB;
}
template <typename T>
std::vector<T> &operator+=(std::vector<T> &A, const std::vector<T> &B)
{
A.reserve(A.size() + B.size()); // preallocate memory without erase original data
A.insert(A.end(), B.begin(), B.end()); // add B;
return A; // here A could be named AB
}
::
采取了;)
v1 + v2
不代表加法。
@
像在F#中那样使用
按照Bradgonesurfing的回答,很多时候并不需要真的将两个向量(O(n))串联起来,而是像对待它们一样将它们当作串联(O(1))来使用。如果是这种情况,则无需Boost库即可完成。
诀窍是创建一个向量代理:一个包装器类,该类处理对两个向量的引用,在外部将其视为单个连续的向量。
用法
std::vector<int> A{ 1, 2, 3, 4, 5};
std::vector<int> B{ 10, 20, 30 };
VecProxy<int> AB(A, B); // ----> O(1). No copies performed.
for (size_t i = 0; i < AB.size(); ++i)
std::cout << AB[i] << " "; // 1 2 3 4 5 10 20 30
实施方式
template <class T>
class VecProxy {
private:
std::vector<T>& v1, v2;
public:
VecProxy(std::vector<T>& ref1, std::vector<T>& ref2) : v1(ref1), v2(ref2) {}
const T& operator[](const size_t& i) const;
const size_t size() const;
};
template <class T>
const T& VecProxy<T>::operator[](const size_t& i) const{
return (i < v1.size()) ? v1[i] : v2[i - v1.size()];
};
template <class T>
const size_t VecProxy<T>::size() const { return v1.size() + v2.size(); };
主要好处
创建它的时间为O(1)(恒定时间),并且具有最少的额外内存分配。
一些需要考虑的东西
尚未提及的另一种简单变体:
copy(A.begin(),A.end(),std::back_inserter(AB));
copy(B.begin(),B.end(),std::back_inserter(AB));
并使用合并算法:
#include <algorithm>
#include <vector>
#include <iterator>
#include <iostream>
#include <sstream>
#include <string>
template<template<typename, typename...> class Container, class T>
std::string toString(const Container<T>& v)
{
std::stringstream ss;
std::copy(v.begin(), v.end(), std::ostream_iterator<T>(ss, ""));
return ss.str();
};
int main()
{
std::vector<int> A(10);
std::vector<int> B(5); //zero filled
std::vector<int> AB(15);
std::for_each(A.begin(), A.end(),
[](int& f)->void
{
f = rand() % 100;
});
std::cout << "before merge: " << toString(A) << "\n";
std::cout << "before merge: " << toString(B) << "\n";
merge(B.begin(),B.end(), begin(A), end(A), AB.begin(), [](int&,int&)->bool {});
std::cout << "after merge: " << toString(AB) << "\n";
return 1;
}