Related
How do I concatenate two std::vectors?
vector1.insert( vector1.end(), vector2.begin(), vector2.end() );
If you are using C++11, and wish to move the elements rather than merely copying them, you can use std::move_iterator along with insert (or 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;
}
This will not be more efficient for the example with ints, since moving them is no more efficient than copying them, but for a data structure with optimized moves, it can avoid copying unnecessary state:
#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;
}
After the move, src's element is left in an undefined but safe-to-destruct state, and its former elements were transfered directly to dest's new element at the end.
I would use the insert function, something like:
vector<int> a, b;
//fill with data
b.insert(b.end(), a.begin(), a.end());
Or you could use:
std::copy(source.begin(), source.end(), std::back_inserter(destination));
This pattern is useful if the two vectors don't contain exactly the same type of thing, because you can use something instead of std::back_inserter to convert from one type to the other.
With C++11, I'd prefer following to append vector b to a:
std::move(b.begin(), b.end(), std::back_inserter(a));
when a and b are not overlapped, and b is not going to be used anymore.
This is std::move from <algorithm>, not the usual std::move from <utility>.
std::vector<int> first;
std::vector<int> second;
first.insert(first.end(), second.begin(), second.end());
I prefer one that is already mentioned:
a.insert(a.end(), b.begin(), b.end());
But if you use C++11, there is one more generic way:
a.insert(std::end(a), std::begin(b), std::end(b));
Also, not part of a question, but it is advisable to use reserve before appending for better performance. And if you are concatenating vector with itself, without reserving it fails, so you always should reserve.
So basically what you need:
template <typename T>
void Append(std::vector<T>& a, const std::vector<T>& b)
{
a.reserve(a.size() + b.size());
a.insert(a.end(), b.begin(), b.end());
}
With range v3, you may have a lazy concatenation:
ranges::view::concat(v1, v2)
Demo.
A general performance boost for concatenate is to check the size of the vectors. And merge/insert the smaller one with the larger one.
//vector<int> v1,v2;
if(v1.size()>v2.size()) {
v1.insert(v1.end(),v2.begin(),v2.end());
} else {
v2.insert(v2.end(),v1.begin(),v1.end());
}
If you want to be able to concatenate vectors concisely, you could overload the += operator.
template <typename T>
std::vector<T>& operator +=(std::vector<T>& vector1, const std::vector<T>& vector2) {
vector1.insert(vector1.end(), vector2.begin(), vector2.end());
return vector1;
}
Then you can call it like this:
vector1 += vector2;
There is an algorithm std::merge from C++17, which is very easy to use when the input vectors are sorted,
Below is the example:
#include <iostream>
#include <vector>
#include <algorithm>
int main()
{
//DATA
std::vector<int> v1{2,4,6,8};
std::vector<int> v2{12,14,16,18};
//MERGE
std::vector<int> dst;
std::merge(v1.begin(), v1.end(), v2.begin(), v2.end(), std::back_inserter(dst));
//PRINT
for(auto item:dst)
std::cout<<item<<" ";
return 0;
}
You should use vector::insert
v1.insert(v1.end(), v2.begin(), v2.end());
If you are interested in strong exception guarantee (when copy constructor can throw an exception):
template<typename T>
inline void append_copy(std::vector<T>& v1, const std::vector<T>& v2)
{
const auto orig_v1_size = v1.size();
v1.reserve(orig_v1_size + v2.size());
try
{
v1.insert(v1.end(), v2.begin(), v2.end());
}
catch(...)
{
v1.erase(v1.begin() + orig_v1_size, v1.end());
throw;
}
}
Similar append_move with strong guarantee can't be implemented in general if vector element's move constructor can throw (which is unlikely but still).
If your goal is simply to iterate over the range of values for read-only purposes, an alternative is to wrap both vectors around a proxy (O(1)) instead of copying them (O(n)), so they are promptly seen as a single, contiguous one.
std::vector<int> A{ 1, 2, 3, 4, 5};
std::vector<int> B{ 10, 20, 30 };
VecProxy<int> AB(A, B); // ----> O(1)!
for (size_t i = 0; i < AB.size(); i++)
std::cout << AB[i] << " "; // ----> 1 2 3 4 5 10 20 30
Refer to https://stackoverflow.com/a/55838758/2379625 for more details, including the 'VecProxy' implementation as well as pros & cons.
Add this one to your header file:
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;
}
and use it this way:
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 will contain [1,2,62]
Using C++20 you can get rid of begin() and end() with ranges.
#include <ranges>
std::ranges::copy(vec2, std::back_inserter(vec1));
or if you want to move elements:
std::ranges::move(vec2, std::back_inserter(vec1));
Here's a general purpose solution using C++11 move semantics:
template <typename T>
std::vector<T> concat(const std::vector<T>& lhs, const std::vector<T>& rhs)
{
if (lhs.empty()) return rhs;
if (rhs.empty()) return lhs;
std::vector<T> result {};
result.reserve(lhs.size() + rhs.size());
result.insert(result.cend(), lhs.cbegin(), lhs.cend());
result.insert(result.cend(), rhs.cbegin(), rhs.cend());
return result;
}
template <typename T>
std::vector<T> concat(std::vector<T>&& lhs, const std::vector<T>& rhs)
{
lhs.insert(lhs.cend(), rhs.cbegin(), rhs.cend());
return std::move(lhs);
}
template <typename T>
std::vector<T> concat(const std::vector<T>& lhs, std::vector<T>&& rhs)
{
rhs.insert(rhs.cbegin(), lhs.cbegin(), lhs.cend());
return std::move(rhs);
}
template <typename T>
std::vector<T> concat(std::vector<T>&& lhs, std::vector<T>&& rhs)
{
if (lhs.empty()) return std::move(rhs);
lhs.insert(lhs.cend(), std::make_move_iterator(rhs.begin()), std::make_move_iterator(rhs.end()));
return std::move(lhs);
}
Note how this differs from appending to a vector.
You can prepare your own template for + operator:
template <typename T>
inline T operator+(const T & a, const T & b)
{
T res = a;
res.insert(res.end(), b.begin(), b.end());
return res;
}
Next thing - just use +:
vector<int> a{1, 2, 3, 4};
vector<int> b{5, 6, 7, 8};
for (auto x: a + b)
cout << x << " ";
cout << endl;
This example gives output:
1 2 3 4 5 6 7 8
vector<int> v1 = {1, 2, 3, 4, 5};
vector<int> v2 = {11, 12, 13, 14, 15};
copy(v2.begin(), v2.end(), back_inserter(v1));
I've implemented this function which concatenates any number of containers, moving from rvalue-references and copying otherwise
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;
}
This solution might be a bit complicated, but boost-range has also some other nice things to offer.
#include <iostream>
#include <vector>
#include <boost/range/algorithm/copy.hpp>
int main(int, char**) {
std::vector<int> a = { 1,2,3 };
std::vector<int> b = { 4,5,6 };
boost::copy(b, std::back_inserter(a));
for (auto& iter : a) {
std::cout << iter << " ";
}
return EXIT_SUCCESS;
}
Often ones intention is to combine vector a and b just iterate over it doing some operation. In this case, there is the ridiculous simple join function.
#include <iostream>
#include <vector>
#include <boost/range/join.hpp>
#include <boost/range/algorithm/copy.hpp>
int main(int, char**) {
std::vector<int> a = { 1,2,3 };
std::vector<int> b = { 4,5,6 };
std::vector<int> c = { 7,8,9 };
// Just creates an iterator
for (auto& iter : boost::join(a, boost::join(b, c))) {
std::cout << iter << " ";
}
std::cout << "\n";
// Can also be used to create a copy
std::vector<int> d;
boost::copy(boost::join(a, boost::join(b, c)), std::back_inserter(d));
for (auto& iter : d) {
std::cout << iter << " ";
}
return EXIT_SUCCESS;
}
For large vectors this might be an advantage, as there is no copying. It can be also used for copying an generalizes easily to more than one container.
For some reason there is nothing like boost::join(a,b,c), which could be reasonable.
For containers which offer push_back (string, vector, deque, ...):
std::copy(std::begin(input), std::end(input), std::back_inserter(output))
and
for containers which offer insert (maps, sets):
std::copy(std::begin(input), std::end(input), std::inserter(output, output.end()))
If what you're looking for is a way to append a vector to another after creation, vector::insert is your best bet, as has been answered several times, for example:
vector<int> first = {13};
const vector<int> second = {42};
first.insert(first.end(), second.cbegin(), second.cend());
Sadly there's no way to construct a const vector<int>, as above you must construct and then insert.
If what you're actually looking for is a container to hold the concatenation of these two vector<int>s, there may be something better available to you, if:
Your vector contains primitives
Your contained primitives are of size 32-bit or smaller
You want a const container
If the above are all true, I'd suggest using the basic_string who's char_type matches the size of the primitive contained in your vector. You should include a static_assert in your code to validate these sizes stay consistent:
static_assert(sizeof(char32_t) == sizeof(int));
With this holding true you can just do:
const u32string concatenation = u32string(first.cbegin(), first.cend()) + u32string(second.cbegin(), second.cend());
For more information on the differences between string and vector you can look here: https://stackoverflow.com/a/35558008/2642059
For a live example of this code you can look here: http://ideone.com/7Iww3I
You can do it with pre-implemented STL algorithms using a template for a polymorphic type use.
#include <iostream>
#include <vector>
#include <algorithm>
template<typename T>
void concat(std::vector<T>& valuesa, std::vector<T>& valuesb){
for_each(valuesb.begin(), valuesb.end(), [&](int value){ valuesa.push_back(value);});
}
int main()
{
std::vector<int> values_p={1,2,3,4,5};
std::vector<int> values_s={6,7};
concat(values_p, values_s);
for(auto& it : values_p){
std::cout<<it<<std::endl;
}
return 0;
}
You can clear the second vector if you don't want to use it further (clear() method).
Concatenate two std::vector-s with for loop in one std::vector.
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];
}
To be honest, you could fast concatenate two vectors by copy elements from two vectors into the other one or just only append one of two vectors!. It depends on your aim.
Method 1: Assign new vector with its size is the sum of two original vectors' size.
vector<int> concat_vector = vector<int>();
concat_vector.setcapacity(vector_A.size() + vector_B.size());
// Loop for copy elements in two vectors into concat_vector
Method 2: Append vector A by adding/inserting elements of vector B.
// Loop for insert elements of vector_B into vector_A with insert()
function: vector_A.insert(vector_A .end(), vector_B.cbegin(), vector_B.cend());
Try, create two vectors and add second vector to first vector,
code:
std::vector<int> v1{1,2,3};
std::vector<int> v2{4,5};
for(int i = 0; i<v2.size();i++)
{
v1.push_back(v2[i]);
}
v1:1,2,3.
Description:
While i int not v2 size, push back element , index i in v1 vector.
I'm trying to "convert" an integer C style array to std::vector<int*> without using a for loop, or rather insert pointers of all array items in a vector.
I'm currently implementing this by doing the follow:
for (size_t i = 0; i < 5; i++)
{
vector.push_back(&values[i]);
}
Is it possible to implement this by using std::vector::insert() and std::being/end?
std::transform is a useful algorithm in <algorithm> for copying values between containers that aren't implicitly compatible but for which you can provide a transformation function.
Here is an example of how you could populate a std::vector<int*> from a std::array<int, N>
int values[5] = { 1,2,3,4,5 };
std::vector<int*> v1;
std::transform(
std::begin(values), std::end(values), // Copy from
std::back_inserter(v1), // Copy to
[](auto& i) { // Transformation function
return &i;
});
Edit : Changed std::array<int, 5> to int[5] to account for edits in the question.
The code below is rather fancy way to do what you want, but it is generic and it doesn't use for loop - it just passes pointers of array's elements to vector constructor:
template<class T, size_t ... Ints, size_t N>
std::vector<T*> makePtrsHelper(std::array<T,N>& arr, std::index_sequence<Ints...>) {
return std::vector<T*>{ & std::get<Ints>(arr)... };
// vector ctor taking pointers to array's elements
}
template<class T, size_t N>
std::vector<T*> makePtrs(std::array<T,N>& array) {
return makePtrsHelper(array, std::make_index_sequence<N>{});
}
int main(){
std::array<int,5> ar{1,2,3,4,5};
std::vector<int*> v = makePtrs(ar);
Live demo
Note: as pointed out in comments my below answer is wrongly related to vector<int> not vector<int*> which was asked for in question.
Solution with std::copy and C-style array:
int ar[] = {1,2,3,4,3,2,1};
std::vector<int> vec;
std::copy(ar, ar+sizeof(ar)/sizeof(ar[0]), back_inserter(vec));
What is elegant way to insert an element to particular position of std::vector ?
If std::vector has size less than a position.
For example:
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> vec(8);
vec.insert(vec.begin() + 200, 5); // fail, I need auto-resize
}
Use std::vector::resize, with appropriate argument. Say you have your:
std::vector<int> vec(8);
Simply use:
vec.resize(201);
vec.insert(vec.begin() + 200, 5);
You could also wrap it around your own template function, which could check for possibly needed allocation:
template<class T>
void safe_insert(std::vector<T>& vec, const size_t pos, const T arg)
{
if(vec.size() <= pos) vec.resize(pos);
vec.insert(vec.begin() + pos, arg);
}
Calling it like so:
std::vector<int> vec(8);
safe_insert(vec, 200, 5);
std::cout << vec[200];
The code outputs: 5.
For example
struct A
{
static vector<int> s;
};
vector<int> A::s = {1, 2, 3};
However, my compiler doesn't support initialization list. Any way to implement it easily? Does lambda function help here?
Any way to implement it easily?
There's nothing particularly elegant. You can either copy the data from a static array, or initialise it with the result of a function call. The former might use more memory than you'd like, and the latter needs some slightly messy code.
Boost has a library to make that slightly less ugly:
#include <boost/assign/list_of.hpp>
vector<int> A::s = boost::assign::list_of(1)(2)(3);
Does lambda function help here?
Yes, it can save you from having to name a function just to initialise the vector:
vector<int> A::s = [] {
vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
return v;
}();
(Strictly speaking, this should have an explicit return type, []()->vector<int>, since the lambda body contains more than just a return statement. Some compilers will accept my version, and I believe it will become standard in 2014.)
I always fear being shot down for initialization ordering here for questions like this, but..
#include <iostream>
#include <vector>
#include <iterator>
struct A
{
static std::vector<int> s;
};
static const int s_data[] = { 1,2,3 };
std::vector<int> A::s(std::begin(s_data), std::end(s_data));
int main()
{
std::copy(A::s.begin(), A::s.end(),
std::ostream_iterator<int>(std::cout, " "));
return 0;
}
Output
1 2 3
Just because you can doesn't mean you should =P
Winning the award for the least efficient way to do this:
#include <iostream>
#include <vector>
#include <cstdlib>
using namespace std;
template<typename T>
std::vector<T> v_init(const T& t)
{
return std::vector<T>(1,t);
}
template<typename T, typename... Args>
std::vector<T> v_init(T&& t, Args&&... args)
{
const T values[] = { t, args... };
std::vector<T> v1(std::begin(values), std::end(values));
return v1;
}
struct A
{
static std::vector<int> s;
};
std::vector<int> A::s(v_init(1,2,3,4,5));
int main(int argc, const char *argv[])
{
std::copy(A::s.begin(), A::s.end(), std::ostream_iterator<int>(std::cout, " "));
return 0;
}
Output
1 2 3 4 5
This should puke at compile-time if T and anything in Args... is not type-compliant or type-castable. Of course, if you have variadic templates odds are you also have initializer lists, but it makes for fun brain-food if nothing else.
Write a simple init function for the vector:
vector<int> init()
{
vector<int> v;
v.reserve(3);
v.push_back(1);
v.push_back(2);
v.push_back(3);
return v;
};
vector<int> A::s = init();
You can initialize an std::vector from two pointers
int xv[] = {1,2,3,4,5,6,7,8,9};
std::vector<int> x(xv, xv+(sizeof(xv)/sizeof(xv[0])));
You can even factor this out in a template function:
template<typename T, int n>
std::vector<T> from_array(T (&v)[n]) {
return std::vector<T>(v, v+n);
}
Another idea:
struct A
{
static std::vector<int> s;
};
std::vector<int> A::s;
static bool dummy((A::s.push_back(1), A::s.push_back(2), A::s.push_back(3), false));
I can create an array and initialize it like this:
int a[] = {10, 20, 30};
How do I create a std::vector and initialize it similarly elegant?
The best way I know is:
std::vector<int> ints;
ints.push_back(10);
ints.push_back(20);
ints.push_back(30);
Is there a better way?
If your compiler supports C++11, you can simply do:
std::vector<int> v = {1, 2, 3, 4};
This is available in GCC as of version 4.4. Unfortunately, VC++ 2010 seems to be lagging behind in this respect.
Alternatively, the Boost.Assign library uses non-macro magic to allow the following:
#include <boost/assign/list_of.hpp>
...
std::vector<int> v = boost::assign::list_of(1)(2)(3)(4);
Or:
#include <boost/assign/std/vector.hpp>
using namespace boost::assign;
...
std::vector<int> v;
v += 1, 2, 3, 4;
But keep in mind that this has some overhead (basically, list_of constructs a std::deque under the hood) so for performance-critical code you'd be better off doing as Yacoby says.
One method would be to use the array to initialize the vector
static const int arr[] = {16,2,77,29};
vector<int> vec (arr, arr + sizeof(arr) / sizeof(arr[0]) );
If you can, use the modern C++[11,14,17,20,...] way:
std::vector<int> ints = {10, 20, 30};
The old way of looping over a variable-length array or using sizeof() is truly terrible on the eyes and completely unnecessary in terms of mental overhead. Yuck.
In C++0x you will be able to do it in the same way that you did with an array, but not in the current standard.
With only language support you can use:
int tmp[] = { 10, 20, 30 };
std::vector<int> v( tmp, tmp+3 ); // use some utility to avoid hardcoding the size here
If you can add other libraries you could try boost::assignment:
vector<int> v = list_of(10)(20)(30);
To avoid hardcoding the size of an array:
// option 1, typesafe, not a compile time constant
template <typename T, std::size_t N>
inline std::size_t size_of_array( T (&)[N] ) {
return N;
}
// option 2, not typesafe, compile time constant
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
// option 3, typesafe, compile time constant
template <typename T, std::size_t N>
char (&sizeof_array( T(&)[N] ))[N]; // declared, undefined
#define ARRAY_SIZE(x) sizeof(sizeof_array(x))
In C++11:
#include <vector>
using std::vector;
...
vector<int> vec1 { 10, 20, 30 };
// or
vector<int> vec2 = { 10, 20, 30 };
Using Boost list_of:
#include <vector>
#include <boost/assign/list_of.hpp>
using std::vector;
...
vector<int> vec = boost::assign::list_of(10)(20)(30);
Using Boost assign:
#include <vector>
#include <boost/assign/std/vector.hpp>
using std::vector;
...
vector<int> vec;
vec += 10, 20, 30;
Conventional STL:
#include <vector>
using std::vector;
...
static const int arr[] = {10,20,30};
vector<int> vec (arr, arr + sizeof(arr) / sizeof(arr[0]) );
Conventional STL with generic macros:
#include <vector>
#define ARRAY_SIZE(ar) (sizeof(ar) / sizeof(ar[0])
#define ARRAY_END(ar) (ar + ARRAY_SIZE(ar))
using std::vector;
...
static const int arr[] = {10,20,30};
vector<int> vec (arr, ARRAY_END(arr));
Conventional STL with a vector initializer macro:
#include <vector>
#define INIT_FROM_ARRAY(ar) (ar, ar + sizeof(ar) / sizeof(ar[0])
using std::vector;
...
static const int arr[] = {10,20,30};
vector<int> vec INIT_FROM_ARRAY(arr);
I tend to declare
template< typename T, size_t N >
std::vector<T> makeVector( const T (&data)[N] )
{
return std::vector<T>(data, data+N);
}
in a utility header somewhere and then all that's required is:
const double values[] = { 2.0, 1.0, 42.0, -7 };
std::vector<double> array = makeVector(values);
Before C++ 11:
Method 1
vector<int> v(arr, arr + sizeof(arr)/sizeof(arr[0]));
Method 2
vector<int>v;
v.push_back(SomeValue);
C++ 11 onward below is also possible
vector<int>v = {1, 3, 5, 7};
We can do this as well
vector<int>v {1, 3, 5, 7}; // Notice .. no "=" sign
For C++ 17 onwards we can omit the type
vector v = {1, 3, 5, 7};
Starting with:
int a[] = {10, 20, 30}; //I'm assuming 'a' is just a placeholder
If you don't have a C++11 compiler and you don't want to use Boost:
const int a[] = {10, 20, 30};
const std::vector<int> ints(a, a+sizeof(a)/sizeof(int)); //Make it const if you can
If you don't have a C++11 compiler and can use Boost:
#include <boost/assign.hpp>
const std::vector<int> ints = boost::assign::list_of(10)(20)(30);
If you do have a C++11 compiler:
const std::vector<int> ints = {10,20,30};
For vector initialisation -
vector<int> v = {10, 20, 30}
can be done if you have a C++11 compiler.
Else, you can have an array of the data and then use a for loop.
int array[] = {10,20,30}
for(unsigned int i=0; i<sizeof(array)/sizeof(array[0]); i++)
{
v.push_back(array[i]);
}
Apart from these, there are various other ways described in previous answers using some code. In my opinion, these ways are easy to remember and quick to write.
The easiest way to do it is:
vector<int> ints = {10, 20, 30};
If your compiler supports Variadic macros (which is true for most modern compilers), then you can use the following macro to turn vector initialization into a one-liner:
#define INIT_VECTOR(type, name, ...) \
static const type name##_a[] = __VA_ARGS__; \
vector<type> name(name##_a, name##_a + sizeof(name##_a) / sizeof(*name##_a))
With this macro, you can define an initialized vector with code like this:
INIT_VECTOR(int, my_vector, {1, 2, 3, 4});
This would create a new vector of ints named my_vector with the elements 1, 2, 3, 4.
I build my own solution using va_arg. This solution is C++98 compliant.
#include <cstdarg>
#include <iostream>
#include <vector>
template <typename T>
std::vector<T> initVector (int len, ...)
{
std::vector<T> v;
va_list vl;
va_start(vl, len);
for (int i = 0; i < len; ++i)
v.push_back(va_arg(vl, T));
va_end(vl);
return v;
}
int main ()
{
std::vector<int> v = initVector<int> (7,702,422,631,834,892,104,772);
for (std::vector<int>::const_iterator it = v.begin() ; it != v.end(); ++it)
std::cout << *it << std::endl;
return 0;
}
Demo
If you don't want to use Boost, but want to enjoy syntax like
std::vector<int> v;
v+=1,2,3,4,5;
just include this chunk of code
template <class T> class vector_inserter{
public:
std::vector<T>& v;
vector_inserter(std::vector<T>& v):v(v){}
vector_inserter& operator,(const T& val){v.push_back(val);return *this;}
};
template <class T> vector_inserter<T> operator+=(std::vector<T>& v,const T& x){
return vector_inserter<T>(v),x;
}
In C++11:
static const int a[] = {10, 20, 30};
vector<int> vec (begin(a), end(a));
A more recent duplicate question has this answer by Viktor Sehr. For me, it is compact, visually appealing (looks like you are 'shoving' the values in), doesn't require C++11 or a third-party module, and avoids using an extra (written) variable. Below is how I am using it with a few changes. I may switch to extending the function of vector and/or va_arg in the future instead.
// Based on answer by "Viktor Sehr" on Stack Overflow
// https://stackoverflow.com/a/8907356
//
template <typename T>
class mkvec {
public:
typedef mkvec<T> my_type;
my_type& operator<< (const T& val) {
data_.push_back(val);
return *this;
}
my_type& operator<< (const std::vector<T>& inVector) {
this->data_.reserve(this->data_.size() + inVector.size());
this->data_.insert(this->data_.end(), inVector.begin(), inVector.end());
return *this;
}
operator std::vector<T>() const {
return data_;
}
private:
std::vector<T> data_;
};
std::vector<int32_t> vec1;
std::vector<int32_t> vec2;
vec1 = mkvec<int32_t>() << 5 << 8 << 19 << 79;
// vec1 = (5, 8, 19, 79)
vec2 = mkvec<int32_t>() << 1 << 2 << 3 << vec1 << 10 << 11 << 12;
// vec2 = (1, 2, 3, 5, 8, 19, 79, 10, 11, 12)
You can do that using boost::assign:
vector<int> values;
values += 1,2,3,4,5,6,7,8,9;
Details are here.
The below methods can be used to initialize the vector in C++.
int arr[] = {1, 3, 5, 6}; vector<int> v(arr, arr + sizeof(arr)/sizeof(arr[0]));
vector<int>v; v.push_back(1); v.push_back(2); v.push_back(3); and so on
vector<int>v = {1, 3, 5, 7};
The third one is allowed only in C++11 onwards.
There are a lot of good answers here, but since I independently arrived at my own before reading this, I figured I'd toss mine up here anyway...
Here's a method that I'm using for this which will work universally across compilers and platforms:
Create a struct or class as a container for your collection of objects. Define an operator overload function for <<.
class MyObject;
struct MyObjectList
{
std::list<MyObject> objects;
MyObjectList& operator<<( const MyObject o )
{
objects.push_back( o );
return *this;
}
};
You can create functions which take your struct as a parameter, e.g.:
someFunc( MyObjectList &objects );
Then, you can call that function, like this:
someFunc( MyObjectList() << MyObject(1) << MyObject(2) << MyObject(3) );
That way, you can build and pass a dynamically sized collection of objects to a function in one single clean line!
If you want something on the same general order as Boost::assign without creating a dependency on Boost, the following is at least vaguely similar:
template<class T>
class make_vector {
std::vector<T> data;
public:
make_vector(T const &val) {
data.push_back(val);
}
make_vector<T> &operator,(T const &t) {
data.push_back(t);
return *this;
}
operator std::vector<T>() { return data; }
};
template<class T>
make_vector<T> makeVect(T const &t) {
return make_vector<T>(t);
}
While I wish the syntax for using it was cleaner, it's still not particularly awful:
std::vector<int> x = (makeVect(1), 2, 3, 4);
typedef std::vector<int> arr;
arr a {10, 20, 30}; // This would be how you initialize while defining
To compile use:
clang++ -std=c++11 -stdlib=libc++ <filename.cpp>
// Before C++11
// I used following methods:
// 1.
int A[] = {10, 20, 30}; // original array A
unsigned sizeOfA = sizeof(A)/sizeof(A[0]); // calculate the number of elements
// declare vector vArrayA,
std::vector<int> vArrayA(sizeOfA); // make room for all
// array A integers
// and initialize them to 0
for(unsigned i=0; i<sizeOfA; i++)
vArrayA[i] = A[i]; // initialize vector vArrayA
//2.
int B[] = {40, 50, 60, 70}; // original array B
std::vector<int> vArrayB; // declare vector vArrayB
for (unsigned i=0; i<sizeof(B)/sizeof(B[0]); i++)
vArrayB.push_back(B[i]); // initialize vArrayB
//3.
int C[] = {1, 2, 3, 4}; // original array C
std::vector<int> vArrayC; // create an empty vector vArrayC
vArrayC.resize(sizeof(C)/sizeof(C[0])); // enlarging the number of
// contained elements
for (unsigned i=0; i<sizeof(C)/sizeof(C[0]); i++)
vArrayC.at(i) = C[i]; // initialize vArrayC
// A Note:
// Above methods will work well for complex arrays
// with structures as its elements.
It is pretty convenient to create a vector inline without defining variable when writing test, for example:
assert(MyFunction() == std::vector<int>{1, 3, 4}); // <- this.
"How do I create an STL vector and initialize it like the above? What is the best way to do so with the minimum typing effort?"
The easiest way to initialize a vector as you've initialized your built-in array is using an initializer list which was introduced in C++11.
// Initializing a vector that holds 2 elements of type int.
Initializing:
std::vector<int> ivec = {10, 20};
// The push_back function is more of a form of assignment with the exception of course
//that it doesn't obliterate the value of the object it's being called on.
Assigning
ivec.push_back(30);
ivec is 3 elements in size after Assigning (labeled statement) is executed.
There are various ways to hardcode a vector. I will share few ways:
Initializing by pushing values one by one
// Create an empty vector
vector<int> vect;
vect.push_back(10);
vect.push_back(20);
vect.push_back(30);
Initializing like arrays
vector<int> vect{ 10, 20, 30 };
Initializing from an array
int arr[] = { 10, 20, 30 };
int n = sizeof(arr) / sizeof(arr[0]);
vector<int> vect(arr, arr + n);
Initializing from another vector
vector<int> vect1{ 10, 20, 30 };
vector<int> vect2(vect1.begin(), vect1.end());
If the array is:
int arr[] = {1, 2, 3};
int len = (sizeof(arr)/sizeof(arr[0])); // finding length of array
vector < int > v;
v.assign(arr, arr+len); // assigning elements from array to vector
Related, you can use the following if you want to have a vector completely ready to go in a quick statement (e.g. immediately passing to another function):
#define VECTOR(first,...) \
([](){ \
static const decltype(first) arr[] = { first,__VA_ARGS__ }; \
std::vector<decltype(first)> ret(arr, arr + sizeof(arr) / sizeof(*arr)); \
return ret;})()
example function
template<typename T>
void test(std::vector<T>& values)
{
for(T value : values)
std::cout<<value<<std::endl;
}
example use
test(VECTOR(1.2f,2,3,4,5,6));
though be careful about the decltype, make sure the first value is clearly what you want.
B. Stroustrup describes a nice way to chain operations in 16.2.10 Selfreference on page 464 in the C++11 edition of the Prog. Lang. where a function returns a reference, here modified to a vector. This way you can chain like v.pb(1).pb(2).pb(3); but may be too much work for such small gains.
#include <iostream>
#include <vector>
template<typename T>
class chain
{
private:
std::vector<T> _v;
public:
chain& pb(T a) {
_v.push_back(a);
return *this;
};
std::vector<T> get() { return _v; };
};
using namespace std;
int main(int argc, char const *argv[])
{
chain<int> v{};
v.pb(1).pb(2).pb(3);
for (auto& i : v.get()) {
cout << i << endl;
}
return 0;
}
1
2
3
The simplest, ergonomic way (with C++ 11 or later):
auto my_ints = {1,2,3};
In case you want to have it in your own class:
#include <initializer_list>
Vector<Type>::Vector(std::initializer_list<Type> init_list) : _size(init_list.size()),
_capacity(_size),
_data(new Type[_size])
{
int idx = 0;
for (auto it = init_list.begin(); it != init_list.end(); ++it)
_data[idx++] = *it;
}