Я могу создать массив и инициализировать его следующим образом:
int a[] = {10, 20, 30};
Как мне создать std::vector
и инициализировать его так же элегантно?
Лучший способ, который я знаю, это:
std::vector<int> ints;
ints.push_back(10);
ints.push_back(20);
ints.push_back(30);
Есть ли лучший способ?
Если ваш компилятор поддерживает C++11, вы можете просто сделать:
std::vector<int> v = {1, 2, 3, 4};
Это доступно в GCC начиная с версии 4.4. К сожалению, VC++ 2010, похоже, отстает в этом отношении.
В качестве альтернативы, библиотека Boost.Assign использует не-макро магию, чтобы позволить следующее:
#include <boost/assign/list_of.hpp>
...
std::vector<int> v = boost::assign::list_of(1)(2)(3)(4);
Или:
#include <boost/assign/std/vector.hpp>
using namespace boost::assign;
...
std::vector<int> v;
v += 1, 2, 3, 4;
Но имейте в виду, что это имеет некоторые накладные расходы (по сути, list_of
строит std::deque
под капотом), поэтому для критичного к производительности кода вам лучше поступить так, как говорит Yacoby.
Если вы можете, использовать современный c++[11,14,17,...] образом:
std::vector<int> vec = {10,20,30};
Старый способ цикл по переменной длины массива или используя оператор sizeof () - это поистине страшная на глазах и совершенно ненужных с точки зрения умственной нагрузки. Фу.
В C++0x вы сможете делать это так же, как и с массивом, но не в текущем стандарте.
Вы можете использовать только языковую поддержку:
int tmp[] = { 10, 20, 30 };
std::vector<int> v( tmp, tmp+3 ); // use some utility to avoid hardcoding the size here
Если вы можете добавить другие библиотеки, вы можете попробовать boost::assignment:
vector<int> v = list_of(10)(20)(30);
Чтобы избежать жесткого кодирования размера массива:
// 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))
В C++11:
#include <vector>
using std::vector;
...
vector<int> vec1 { 10, 20, 30 };
// or
vector<int> vec2 = { 10, 20, 30 };
Используя импульс list_of:
#include <vector>
#include <boost/assign/list_of.hpp>
using std::vector;
...
vector<int> vec = boost::assign::list_of(10)(20)(30);
Используя импульс, назначение:
#include <vector>
#include <boost/assign/std/vector.hpp>
using std::vector;
...
vector<int> vec;
vec += 10, 20, 30;
Обычные стл:
#include <vector>
using std::vector;
...
static const int arr[] = {10,20,30};
vector<int> vec (arr, arr + sizeof(arr) / sizeof(arr[0]) );
Обычные стл с общих макросов:
#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));
Обычные стл с вектором инициализации макроса:
#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);
Просто думал, что я'd и кидаешь в мои $0.02. Я склонен заявить об этом:
template< typename T, size_t N >
std::vector<T> makeVector( const T (&data)[N] )
{
return std::vector<T>(data, data+N);
}
в заголовке утилита где-то и все, что'ы необходимо:
const double values[] = { 2.0, 1.0, 42.0, -7 };
std::vector<double> array = makeVector(values);
Но я могу't ждать для C++0х. Я'м застрял, потому что мой код должен компилироваться в Visual студии. Бу.
До C++ 11 :
Способ 1=>
vector<int> v(arr, arr + sizeof(arr)/sizeof(arr[0]));
vector<int>v;
Способ 2 =>
v.push_back(SomeValue);
В C++ 11 и далее ниже тоже можно
vector<int>v = {1, 3, 5, 7};
Начиная с:
int a[] = {10, 20, 30}; //i'm assuming a is just a placeholder
Если вы Don'т иметь компилятор C++11 и вы Don'т хотите использовать boost:
const int a[] = {10, 20, 30};
const std::vector<int> ints(a,a+sizeof(a)/sizeof(int)); //make it const if you can
Если вы Don'т иметь компилятор C++11 и можете использовать импульс:
#include <boost/assign.hpp>
const std::vector<int> ints = boost::assign::list_of(10)(20)(30);
Если у вас есть компилятор C++11:
const std::vector<int> ints = {10,20,30};
Самый простой способ сделать это:
vector<int> ints = {10, 20, 30};
Для вектора инициализации -
vector<int> v = {10,20,30}
можно сделать, если у вас есть компилятор C++11.
Еще, вы можете иметь массив данных, а затем использовать цикл for.
int array[] = {10,20,30}
for(unsigned int i=0; i<sizeof(array)/sizeof(array[0]); i++)
{
v.push_back(array[i]);
}
Помимо этого, существуют различные другие способы, описанные выше, используя определенный код. На мой взгляд, эти способы легко запомнить и быстро записать.
Если ваш компилятор поддерживает макросы с переменным числом аргументов (что справедливо для большинства современных компиляторов), то вы можете использовать следующий макрос для поворота вектора инициализации в один-лайнер:
#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))
С помощью этого макроса можно определить инициализировать вектор с такой код:
INIT_VECTOR(int, my_vector, {1, 2, 3, 4});
Это создаст новый вектор ИНЦ имени my_vector с элементами 1, 2, 3, 4.
Я строю мой собственный решение, используя как va_arg
. Этот раствор совместимый с++98.
#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;
}
Если вы Don'т хотите использовать импульс, но хотите насладиться следующий синтаксис
std::vector<int> v;
v+=1,2,3,4,5;
просто включить этот кусок кода
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;
}
вы можете сделать это с помощью Boost::назначение.
vector<int> values;
values += 1,2,3,4,5,6,7,8,9;
Более последние дублировать вопрос этот ответ по Виктор Зер. Для меня это компактная, визуально привлекательная (похоже, вы 'толкать' значений), не'т требуют c++11 или стороннего модуля, и позволяет избежать использования дополнительной (письменно) переменной. Ниже, как я использую его с некоторыми изменениями. Я может переключиться на расширение функции векторного и/или как va_arg в будущем вместо этого.
// 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)
Ниже методы могут быть использованы для инициализации вектора в C++.
инт Арр[] = {1, 3, 5, 6}; вектор и Л;int> в(Арр Арр + оператор sizeof(Арр)/размер(модуль arr[0]));
вектор и Л;int>в; В. push_back(1); В. push_back(2); В. push_back(3); и так далее
вектор и Л;int>в = {1, 3, 5, 7};`
Третий допускается только в C++11 и далее.
// 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.
Если вы хотите что-то на том же общем порядке, как повышение::связать, не создавая зависимость от наддува, ниже хотя бы отдаленно похожее:
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);
}
Пока я желаю синтаксис для использования он был чище, это's по-прежнему не особенно ужасно:
std::vector<int> x = (makeVect(1), 2, 3, 4);
Есть много хороших ответов здесь, но так как я самостоятельно приехал в мой собственный прежде чем читать это, я понял, что я'д отбросим мою сюда в любом случае...
Здесь's не способ, что я'м, используя для этого, который будет работать универсально на разных компиляторах и платформах:
Создать структуру или класс в качестве контейнера для сбора объектов. Определим функцию перегрузки оператора <<.
class MyObject;
struct MyObjectList
{
std::list<MyObject> objects;
MyObjectList& operator<<( const MyObject o )
{
objects.push_back( o );
return *this;
}
};
Вы можете создавать функции, которые принимают структуру в качестве параметра, например:
someFunc( MyObjectList &objects );
Затем вы можете вызывать эту функцию, как это:
someFunc( MyObjectList() << MyObject(1) << MyObject(2) << MyObject(3) );
Таким образом, вы можете построить и передать динамически размера коллекции объектов функции в одном Чистая линия!