使用硬编码元素初始化std::向量的最简单方法是什么?

我可以创建一个数组并像这样初始化它:

int a[] = {10, 20, 30};

如何创建std::vector并将其初始化为同样优雅?

我知道的最好的方法是:

std::vector<int> ints;


ints.push_back(10);
ints.push_back(20);
ints.push_back(30);

有没有更好的办法?

1053315 次浏览

在C++0x中,您将能够以与数组相同的方式执行此操作,但不是在当前标准中。

只有语言支持,您可以使用:

int tmp[] = { 10, 20, 30 };
std::vector<int> v( tmp, tmp+3 ); // use some utility to avoid hardcoding the size here

如果你可以添加其他库,你可以尝试提升::a的签名:

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))

一种方法是使用数组初始化向量

static const int arr[] = {16,2,77,29};
vector<int> vec (arr, arr + sizeof(arr) / sizeof(arr[0]) );

如果您的编译器支持C++11,您可以简单地执行以下操作:

std::vector<int> v = {1, 2, 3, 4};

这在GCC从版本4.4中可用。不幸的是,VC++2010在这方面似乎落后了。

或者,提升分配库使用非宏魔法来允许以下内容:

#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所说的那样做。

您可以使用提升::a标志执行此操作:

vector<int> values;
values += 1,2,3,4,5,6,7,8,9;

详情在这里

如果你想要与Boost相同的一般顺序,而不需要创建对Boost的依赖,那么以下内容至少是模糊的:

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);
}

虽然我希望使用它的语法更清晰,但它仍然不是特别糟糕:

std::vector<int> x = (makeVect(1), 2, 3, 4);

如果您的编译器支持可变宏(对于大多数现代编译器来说都是如此),那么您可以使用以下宏将向量初始化转换为单行:

#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。

我倾向于宣布

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);

如果您不想使用Boost,但想享受以下语法

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;
}

最简单的方法是:

vector<int> ints = {10, 20, 30};

"如何创建一个STL向量并像上面那样初始化它?用最少的键入努力做到这一点的最佳方法是什么?"

在初始化内置数组时初始化向量的最简单方法是使用初始化器列表它是在11C++推出的

// 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在执行分配(标记语句)后的大小为3个元素。

相关的,如果您想在快速语句中完全准备好向量(例如立即传递给另一个函数),您可以使用以下内容:

#define VECTOR(first,...) \
([](){ \
static const decltype(first) arr[] = { first,__VA_ARGS__ }; \
std::vector<decltype(first)> ret(arr, arr + sizeof(arr) / sizeof(*arr)); \
return ret;})()

示例函数

template<typename T>
void test(std::vector<T>& values)
{
for(T value : values)
std::cout<<value<<std::endl;
}

示例使用

test(VECTOR(1.2f,2,3,4,5,6));

尽管要小心解密类型,但要确保第一个值显然是您想要的。

C++11:

#include <vector>
using std::vector;
...
vector<int> vec1 { 10, 20, 30 };
// or
vector<int> vec2 = { 10, 20, 30 };

使用Boostlist_of

#include <vector>
#include <boost/assign/list_of.hpp>
using std::vector;
...
vector<int> vec = boost::assign::list_of(10)(20)(30);

使用Boost分配:

#include <vector>
#include <boost/assign/std/vector.hpp>
using std::vector;
...
vector<int> vec;
vec += 10, 20, 30;

常规STL:

#include <vector>
using std::vector;
...
static const int arr[] = {10,20,30};
vector<int> vec (arr, arr + sizeof(arr) / sizeof(arr[0]) );

带有通用宏的常规STL:

#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));

带有向量初始化宏的常规STL:

#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);
typedef std::vector<int> arr;


arr a {10, 20, 30};       // This would be how you initialize while defining

编译使用:

clang++ -std=c++11 -stdlib=libc++  <filename.cpp>

我使用va_arg构建自己的解决方案。该解决方案符合C++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;
}

演示

最近的一个重复问题是这个答案 byViktorSehr。对我来说,它很紧凑,视觉上很吸引人(看起来你在“推挤”值),不需要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++11:

static const int a[] = {10, 20, 30};
vector<int> vec (begin(a), end(a));

开始于:

int a[] = {10, 20, 30}; //I'm assuming 'a' is just a placeholder

如果您没有C++编译器并且不想使用Boost:

const int a[] = {10, 20, 30};
const std::vector<int> ints(a, a+sizeof(a)/sizeof(int)); //Make it const if you can

如果你没有C++编译器,可以使用Boost:

#include <boost/assign.hpp>
const std::vector<int> ints = boost::assign::list_of(10)(20)(30);

如果你有一个C++编译器:

const std::vector<int> ints = {10,20,30};

B. Stroustrup在16.2.10自我中描述了一种链接操作的好方法,在C++11版Prog. Lang464页。其中一个函数返回一个引用,这里修改为一个向量。这样你就可以像v.pb(1).pb(2).pb(3);一样链接,但对于这样的小收益来说可能工作量太大。

#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

以下方法可用于在C++中初始化向量。

  1. int arr[] = {1, 3, 5, 6}; vector<int> v(arr, arr + sizeof(arr)/sizeof(arr[0]));

  2. vector<int>v; v.push_back(1); v.push_back(2); v.push_back(3);

  3. vector<int>v = {1, 3, 5, 7};

第三个只允许在C++11以后。

C++11:

方法1

vector<int> v(arr, arr + sizeof(arr)/sizeof(arr[0]));

方法2

vector<int>v;
v.push_back(SomeValue);

C++11以下也是可能的

vector<int>v = {1, 3, 5, 7};

我们也可以这样做。

vector<int>v {1, 3, 5, 7}; // Notice .. no "=" sign

对于C++17起,我们可以省略类型

vector v = {1, 3, 5, 7};

这里有很多好的答案,但是自从我在阅读这篇文章之前独立地到达了我自己的答案,我想无论如何我都会把我的扔在这里。

这是我正在使用的一种方法,它将在编译器和平台上普遍工作:

创建一个结构或类作为对象集合的容器。为<<定义一个运算符重载函数。

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) );

这样,您就可以在一个干净的行中构建动态大小的对象集合并将其传递给函数!

// 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.

对于向量初始化-

vector<int> v = {10, 20, 30}

如果您有C++11编译器,可以这样做。

否则,您可以拥有一个数据数组,然后使用进行循环。

int array[] = {10,20,30}
for(unsigned int i=0; i<sizeof(array)/sizeof(array[0]); i++)
{
v.push_back(array[i]);
}

除此之外,在前面的答案中还使用一些代码描述了各种其他方法。在我看来,这些方法易于记忆和快速编写。

如果数组是:

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

如果可以,使用现代C++[11,14,17,20,…]方式:

std::vector<int> ints = {10, 20, 30};

在可变长度数组上循环或使用sizeof()的旧方法对眼睛来说真的很糟糕,并且在精神开销方面完全没有必要。恶心。

在编写测试时创建一个向量内联而不定义变量是非常方便的,例如:

assert(MyFunction() == std::vector<int>{1, 3, 4}); // <- this.

最简单,符合人体工程学的方法(C++11或更高版本):

auto my_ints = {1,2,3};

有多种方法可以对向量进行硬编码。我将分享几种方法:

  1. 通过一个接一个地推送值来初始化

    // Create an empty vector
    vector<int> vect;
    
    
    vect.push_back(10);
    vect.push_back(20);
    vect.push_back(30);
    
  2. 像数组一样初始化

    vector<int> vect{ 10, 20, 30 };
    
  3. 从数组初始化

    int arr[] = { 10, 20, 30 };
    int n = sizeof(arr) / sizeof(arr[0]);
    
    
    vector<int> vect(arr, arr + n);
    
  4. 从另一个向量初始化

    vector<int> vect1{ 10, 20, 30 };
    
    
    vector<int> vect2(vect1.begin(), vect1.end());
    

如果您想在自己的类中使用它:

#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;
}