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

Agn*_*ian 577 c++ stl initialization vector

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

int a[] = {10, 20, 30};
Run Code Online (Sandbox Code Playgroud)

如何创建std::vector和初始化它同样优雅?

我知道的最好方法是:

std::vector<int> ints;

ints.push_back(10);
ints.push_back(20);
ints.push_back(30);
Run Code Online (Sandbox Code Playgroud)

有没有更好的办法?

Man*_*uel 606

如果您的编译器支持C++ 11,您只需执行以下操作:

std::vector<int> v = {1, 2, 3, 4};
Run Code Online (Sandbox Code Playgroud)

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

或者,Boost.Assign库使用非宏魔术来允许以下内容:

#include <boost/assign/list_of.hpp>
...
std::vector<int> v = boost::assign::list_of(1)(2)(3)(4);
Run Code Online (Sandbox Code Playgroud)

要么:

#include <boost/assign/std/vector.hpp>
using namespace boost::assign;
...
std::vector<int> v;
v += 1, 2, 3, 4;
Run Code Online (Sandbox Code Playgroud)

但请记住,这有一些开销(基本上是list_of构建一个std::deque引擎盖)所以对于性能关键的代码,你最好不要像Yacoby所说的那样做.

  • @Azurespot你可以初始化它,它将是空的:`std :: vector <T> vector;` (3认同)
  • 以防万一有人对 `std::vector&lt;int&gt; v = {1, 2, 3, 4};` 感到好奇,vector 的 `initializer list constructor` 将被调用来进行这种初始化,可以找到它的文档在 [`C++ 11` 部分](http://www.cplusplus.com/reference/vector/vector/vector/) 中。 (2认同)

Yac*_*oby 530

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

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

  • 我没有降低这一点,但我受到了诱惑.主要是因为这首先只是在使用初始化数组时几乎没有任何东西.然而,这确实是C++的错,而不是你的. (63认同)
  • sizeof(array)是少数几个允许获取数组元素总大小而不是arr指针维度的异常之一.所以基本上他使用的是vector(pointer_to_first_element,pointer_to_first_element + size_in_bytes_of_the_whole_array/size_of_one_element),它是:vector(pointer_to_first_element,pointer_after_final_element).该类型已经使用<int>给出,因此向量知道一个元素的数量.请记住,迭代器可以被视为指针,因此您基本上使用向量(iterator begin,iterator end)构造函数 (12认同)
  • @TED:有时你需要修改结果向量.例如,您可能需要始终拥有一些默认参数,有时会添加一些自定义参数. (11认同)
  • @Agnel它可以在没有`static`或`const`的情况下正常工作,但它们都使它更明确地应该如何使用它并允许编译器进行额外的优化. (7认同)
  • 你能解释为什么在定义vec向量时使用这些参数. (2认同)

Ada*_*son 86

如果可以的话,使用现代的C++ [11,14,17,...]方式:

std::vector<int> vec = {10,20,30};
Run Code Online (Sandbox Code Playgroud)

循环使用可变长度数组或使用的旧方法sizeof()在眼睛上是非常可怕的,并且在心理开销方面完全没有必要.呸.

  • 公平地说,这最初是一个C++ 03问题,但我希望人们/公司采用新标准.C++仍然需要标准库中的可变长度数组(VLA)实现,类似于Eigen和Boost中可用的实现. (2认同)

Dav*_*eas 76

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

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

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

如果你可以添加其他库,你可以试试boost :: assignment:

vector<int> v = list_of(10)(20)(30);
Run Code Online (Sandbox Code Playgroud)

为了避免硬编码数组的大小:

// 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))
Run Code Online (Sandbox Code Playgroud)

  • @Manuel,数组的大小是类型的一部分,因此它是一个编译时常量.现在,选项1使用编译时常量'N'作为函数的返回值.函数的返回不是编译时间,而是运行时值,即使它可能会在调用地点作为常量值内联.区别在于你不能这样做:`int另一个[size_of_array(array)]`,而你可以做`int另一个[ARRAY_SIZE(array)]`. (4认同)
  • 在选项3中:我真的不明白你所说的“已声明,未定义”是什么意思?那么变量不会占用额外的内存吗? (2认同)
  • @To1ne 实际上是一个函数声明,而不是一个变量。定义它的原因是,除了不需要定义的“sizeof”表达式之外,我们实际上不需要该函数用于任何其他用途。虽然您实际上可以提供定义,但要做到正确需要静态分配数组并返回对其的引用,下一个问题是数组的值什么才有意义?(另请注意,这意味着函数实例化的每种类型/大小组合都有一个数组!)由于它没有合理的用途,我宁愿避免它。 (2认同)
  • @mhd:您无法在该语言中构造空数组。'int arr[0] = {};' 不是有效的 C++ 代码。但你是对的,如果你想初始化一个空向量和一个非空向量,你将不得不使用不同的构造。从 C++11 开始,这不是问题,因为您可以使用初始化列表构造函数 (2认同)

mbe*_*lls 57

在C++ 11中:

#include <vector>
using std::vector;
...
vector<int> vec1 { 10, 20, 30 };
// or
vector<int> vec2 = { 10, 20, 30 };
Run Code Online (Sandbox Code Playgroud)

使用boost list_of:

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

使用提升分配:

#include <vector>
#include <boost/assign/std/vector.hpp>
using std::vector;
...
vector<int> vec;
vec += 10, 20, 30;
Run Code Online (Sandbox Code Playgroud)

常规STL:

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

具有通用宏的常规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));
Run Code Online (Sandbox Code Playgroud)

具有向量初始化宏的常规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);
Run Code Online (Sandbox Code Playgroud)

  • C ++ 11还为数组支持`std :: begin`和`std :: end`,因此向量也可以像static const int arr [] = {10,20,30}那样初始化。vector &lt;int&gt; vec(begin(arr),end(arr));`。 (2认同)

M. *_*its 52

只是觉得我要扔掉0.02美元.我倾向于宣布:

template< typename T, size_t N >
std::vector<T> makeVector( const T (&data)[N] )
{
    return std::vector<T>(data, data+N);
}
Run Code Online (Sandbox Code Playgroud)

在某个实用程序标题中,然后所需的只是:

const double values[] = { 2.0, 1.0, 42.0, -7 };
std::vector<double> array = makeVector(values);
Run Code Online (Sandbox Code Playgroud)

但我不能等待C++ 0x.我被困了,因为我的代码也必须在Visual Studio中编译.嘘.

  • 你能解释一下`const T(&data)[N]`部分吗?如何在调用`makeVector(values)`中推断出数组的大小? (4认同)

A J*_*A J 34

在C++ 11之前:

方法1 =>

vector<int> v(arr, arr + sizeof(arr)/sizeof(arr[0]));
vector<int>v;
Run Code Online (Sandbox Code Playgroud)

方法2 =>

 v.push_back(SomeValue);
Run Code Online (Sandbox Code Playgroud)

下面的C++ 11也是可能的

vector<int>v = {1, 3, 5, 7};
Run Code Online (Sandbox Code Playgroud)


Car*_*arl 28

从...开始:

int a[] = {10, 20, 30}; //i'm assuming a is just a placeholder
Run Code Online (Sandbox Code Playgroud)

如果您没有C++ 11编译器而您不想使用boost:

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

如果您没有C++ 11编译器并且可以使用boost:

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

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

const std::vector<int> ints = {10,20,30};
Run Code Online (Sandbox Code Playgroud)


Pau*_*scu 21

最简单的方法是:

vector<int> ints = {10, 20, 30};
Run Code Online (Sandbox Code Playgroud)

  • 哪个编译器?你在这里使用C++ 11吗? (4认同)

小智 20

对于矢量初始化 -

vector<int> v = {10,20,30}
Run Code Online (Sandbox Code Playgroud)

如果你有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]);
}
Run Code Online (Sandbox Code Playgroud)

除了这些之外,还有使用一些代码的上述各种方式.在我看来,这些方法易于记忆和快速编写.


Mat*_*all 14

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

#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))
Run Code Online (Sandbox Code Playgroud)

使用此宏,您可以使用以下代码定义初始化向量:

INIT_VECTOR(int, my_vector, {1, 2, 3, 4});
Run Code Online (Sandbox Code Playgroud)

这将创建一个名为my_vector的新向量,其元素为1,2,3,4.


alo*_*ica 14

我使用构建自己的解决方案va_arg.此解决方案符合C98标准.

#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;
}
Run Code Online (Sandbox Code Playgroud)

演示


Pit*_*kul 12

如果你不想使用boost,但想要享受类似的语法

std::vector<int> v;
v+=1,2,3,4,5;
Run Code Online (Sandbox Code Playgroud)

只需包含这一段代码

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;
}
Run Code Online (Sandbox Code Playgroud)

  • -1 operator + =不应返回对本地构造对象的引用. (6认同)

f4.*_*f4. 10

你可以使用boost :: assign来做到这一点.

vector<int> values;  
values += 1,2,3,4,5,6,7,8,9;
Run Code Online (Sandbox Code Playgroud)

细节在这里

  • 我没有看到更长时间内运营商超载滥用的更糟糕的情况.`+ =`在1,2,3,4 ..到达值的末尾,或者它是_add_ 1到第1个元素,2到第2个元素,3到3个元素(如此语法)应该在类似MATLAB的语言中) (17认同)

小智 10

最近的一个重复的问题有此答案维克托Sehr.对我来说,它是紧凑的,视觉上吸引人的(看起来你正在'推'的价值),不需要c ++ 11或第三方模块,并避免使用额外的(书面)变量.以下是我如何使用它进行一些更改.我可以切换到在将来的intead中扩展vector和/或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)
Run Code Online (Sandbox Code Playgroud)


Buf*_*lls 10

在C++ 11中:

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

  • 如果您已经在使用C++ 11,那么您也可以采用直接方法 - "vector <int> arr = {10,20,30};`. (21认同)

小智 6

下面的方法可用于初始化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之后.


Buv*_*inJ 5

这里有很多很好的答案,但由于我在阅读本文之前独立得出了自己的答案,我想无论如何我都会把我的扔在这里......

这是我为此使用的一种方法,它可以跨编译器和平台普遍工作:

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

class MyObject;

struct MyObjectList
{
    std::list<MyObject> objects;
    MyObjectList& operator<<( const MyObject o )
    { 
        objects.push_back( o );
        return *this; 
    }
};
Run Code Online (Sandbox Code Playgroud)

您可以创建将您的结构作为参数的函数,例如:

someFunc( MyObjectList &objects );
Run Code Online (Sandbox Code Playgroud)

然后,您可以调用该函数,如下所示:

someFunc( MyObjectList() << MyObject(1) <<  MyObject(2) <<  MyObject(3) );
Run Code Online (Sandbox Code Playgroud)

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


sg7*_*sg7 5

// 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.
Run Code Online (Sandbox Code Playgroud)