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?
This question is related to
c++
vector
stl
initialization
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;
}
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>
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.
// 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.
If the array is:
int arr[] = {1, 2, 3};
int len = (sizeof(arr)/sizeof(arr[0])); // finding length of array
vector < int > v;
std:: v.assign(arr, arr+len); // assigning elements from array to vector
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.
In C++11:
static const int a[] = {10, 20, 30};
vector<int> vec (begin(a), end(a));
Just thought I'd toss in my $0.02. I tend to declare this:
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);
But I can't wait for C++0x. I'm stuck because my code must also compile in Visual Studio. Boo.
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);
"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.
The easiest way to do it is:
vector<int> ints = {10, 20, 30};
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;
}
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!
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;
}
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.
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
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 intead.
// 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)
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.
For vector initialisation -
vector<int> v = {10,20,30}
can be done if you have 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 above using some code. In my opinion, these ways are easy to remember and quick to write.
If you can, use the modern C++[11,14,17,...] way:
std::vector<int> vec = {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++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);
There are various ways to hardcode a vector, i will share few ways:
// Create an empty vector
vector<int> vect;
vect.push_back(10);
vect.push_back(20);
vect.push_back(30);
vector<int> vect{ 10, 20, 30 };
int arr[] = { 10, 20, 30 };
int n = sizeof(arr) / sizeof(arr[0]);
vector<int> vect(arr, arr + n);
vector<int> vect1{ 10, 20, 30 };
vector<int> vect2(vect1.begin(), vect1.end());
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.
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))
Before C++ 11 :
Method 1=>
vector<int> v(arr, arr + sizeof(arr)/sizeof(arr[0]));
vector<int>v;
Method 2 =>
v.push_back(SomeValue);
C++ 11 onward below is also possible
vector<int>v = {1, 3, 5, 7};
The simplest, ergonomic way (with C++ 11 or later):
auto my_ints = {1,2,3};
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};
Source: Stackoverflow.com