Reputation: 59506
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?
Upvotes: 735
Views: 1204425
Reputation: 780
static const int arr[] = {10, 20, 30};
vector<int> v(arr, arr + sizeof(arr) / sizeof(arr[0]));
We can also do:
vector<int> v;
v.push_back(SomeValue);
// ...
Using copy-list-initialization:
vector<int> v = {1, 3, 5, 7};
We can do this using direct-list-initialization well:
vector<int> v {1, 3, 5, 7}; // Notice .. no "=" sign
Class template argument deduction (CTAD) lets you omit the template arguments:
vector v = {1, 3, 5, 7};
Upvotes: 49
Reputation: 6363
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.
Upvotes: 144
Reputation: 3170
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
Upvotes: 4
Reputation: 3852
You can do that using boost::assign:
vector<int> values;
values += 1,2,3,4,5,6,7,8,9;
Upvotes: 8
Reputation: 8640
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);
Upvotes: 59
Reputation: 2120
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;
}
Upvotes: 13
Reputation: 3858
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);
Upvotes: 81
Reputation: 44488
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};
Upvotes: 29
Reputation: 126
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)
Upvotes: 10
Reputation: 207
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.
Upvotes: 7
Reputation: 339
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.
Upvotes: 23
Reputation: 145
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());
Upvotes: 4
Reputation: 7393
The simplest, ergonomic way (with C++ 11 or later):
auto my_ints = {1,2,3};
Upvotes: 1
Reputation: 41
"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.
Upvotes: 4
Reputation: 11076
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!
Upvotes: 5
Reputation: 683
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;
}
Upvotes: 0
Reputation: 1120
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.
Upvotes: 4
Reputation: 23531
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;
}
Upvotes: 16
Reputation: 6298
// 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.
Upvotes: 4
Reputation: 7832
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
Upvotes: 2
Reputation: 8103
In C++11:
static const int a[] = {10, 20, 30};
vector<int> vec (begin(a), end(a));
Upvotes: 11
Reputation: 2083
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>
Upvotes: 4
Reputation: 13119
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.
Upvotes: 790
Reputation: 208436
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))
Upvotes: 82
Reputation: 183
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.
Upvotes: 3
Reputation: 2255
The easiest way to do it is:
vector<int> ints = {10, 20, 30};
Upvotes: 22
Reputation: 1502
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.
Upvotes: 16
Reputation: 490518
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);
Upvotes: 4
Reputation: 55465
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]) );
Upvotes: 589