我可以创建一个数组并按如下方式对其进行初始化:

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


如何创建std::vector并进行类似的初始化?

最好我知道的方法是:

std::vector<int> ints;

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


还有更好的方法吗?

评论

如果您不打算在初始化后更改int的大小,请考虑使用tr1数组。

@zr,您让我感到好奇...如果我需要固定大小,我自己可以不使用普通的旧数组吗?现在看tr1数组...

tr1 :: array很有用,因为普通数组不提供STL容器的接口

更改标题以使其明确成为C ++ 03问题。这似乎比遍历并修复所有答案以使新标准C ++变得有意义要容易得多。

这称为列表初始化。

#1 楼

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

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


评论


@Agnel在没有static或const的情况下,它可以很好地工作,但是它们都使它在使用方式上更加明确,并允许编译器进行其他优化。

– Yacoby
2010-2-10在16:55

我没有拒绝,但是我很想。主要是因为仅使用初始化数组就可以为您节省几乎什么。但是,这实际上是C ++的错误,而不是您的错误。

– T.E.D.
2011年5月3日18:50

您能否解释一下为什么在定义vec向量时使用这些参数。

– DomX23
2012年1月27日下午5:23

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)。该类型已经使用给出,因此向量知道一个元素有多少。请记住,迭代器可以视为指针,因此您基本上是在使用vector(迭代器开始,迭代器结束)构造函数

–约翰尼·鲍林(Johnny Pauling)
2012年8月17日12:58

@ T.E.D:有时您需要修改结果向量。例如,您可能需要始终具有一些默认参数,有时还需要为其添加一些自定义参数。

– DarkWanderer
14年2月18日在9:24

#2 楼

如果您的编译器支持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所说,这样做会更好。

评论


由于向量是自定义大小的,因此也可以将其初始化为空吗?就像在构造函数中一样:this-> vect = {}; ?

– Azurespot
18-3-8的2:03



@Azurespot您只需对其进行初始化,它将为空:std :: vector vector;

–卢克
18年4月5日在23:33

万一有人可能对std :: vector v = {1,2,3,4}感到好奇,将调用vector的初始化列表构造函数进行这种初始化,可以在C ++ 11中找到其doc。部分。

– simomo
19年3月1日在15:48



#3 楼

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

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


循环遍历可变长度数组的旧方法或使用sizeof()在眼睛上确实很糟糕,就精神负担而言完全没有必要。 uck。

评论


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

–亚当·埃里克森(Adam Erickson)
18-09-16在20:55

不幸的是,这种方法在某些情况下是有问题的,例如open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1467。 uck

–轨道轻赛
19年2月27日在12:31

如果“同类型对象的集合的列表初始化”是您的事,那么您的代码库中可能存在更大的问题……我认为没有任何应用程序可以证明调试问题的合理性。

–亚当·埃里克森(Adam Erickson)
19年6月20日在23:30

从2018年开始回答,仍然使用= {}吗?

–没有一个摊档
8月3日15:01

仍然不需要=

–反斜杠N
9月13日13:34

#4 楼

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


评论


当然我没有投票,但总有一个问题:数组的大小何时不是编译时间常数?也就是说,在哪种情况下,您将在第二个代码段中使用第一个解决方案,而不是第三个代码段?

– Manuel
2010-2-10在11:26

@Manuel,数组的大小是类型的一部分,因此,它是一个编译时间常数。现在,选项1使用该编译时间常数'N'作为函数的返回值。函数的返回不是编译时,而是运行时值,即使它可能在调用位置被内联为常量值也是如此。不同之处在于您不能执行:int another [size_of_array(array)],而可以进行int another [ARRAY_SIZE(array)]。

–DavidRodríguez-dribeas
2010-2-10在11:45



在选项3中:“声明的,未定义的”的意思不是我真正的意思吗?那么变量不会占用额外的内存吗?

–To1ne
2011年6月6日在6:40



@ To1ne实际上是函数声明,而不是变量。定义它的原因是,除了不需要定义的sizeof表达式之外,我们实际上不需要该函数。虽然您实际上可以提供一个定义,但是要正确地执行定义,则需要对数组进行静态分配并返回对其的引用,而下一个问题是作为数组的值有意义吗? (还要注意,这意味着该函数实例化的每个类型/大小组合只有一个数组!)由于对它没有明智的用法,所以我宁愿避免使用它。

–DavidRodríguez-dribeas
2012年1月20日12:51

@mhd:您不能使用该语言构造一个空数组。 'int arr [0] = {};'不是有效的C ++代码。但是正确的是,如果要初始化一个空向量和一个非空向量,则必须使用不同的构造。由于C ++ 11,这不是问题,因为您可以使用初始化程序列表构造函数

–DavidRodríguez-dribeas
16-10-13在11:03

#5 楼

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

常规STL:
#include <vector>
using std::vector;
...
static const int arr[] = {10,20,30};
vector<int> vec (arr, arr + sizeof(arr) / sizeof(arr[0]) );
< br带有常规宏的常规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);


评论


C ++ 11还支持数组的std :: begin和std :: end,因此向量也可以像静态const int arr [] = {10,20,30}一样进行初始化。向量 vec(begin(arr),end(arr));。

– Jaege
16 Dec 17'4:57

#6 楼

只是以为我会扔掉我的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);


但是我等不及C ++ 0x。我被困住了,因为我的代码也必须在Visual Studio中编译。嘘。

评论


此技术还可用于使函数重载以接受具有类型大小的数组。

–安德烈斯·里奥弗里奥(Andres Riofrio)
2012年10月8日在22:03



您能解释const T(&data)[N]部分吗?如何在调用makeVector(values)中推导数组的大小?

–Patryk
2015年3月12日15:04



#7 楼

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


#8 楼

始于:

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


如果您没有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


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

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


#9 楼

对于向量初始化-如果您具有C ++ 11编译器,则可以完成
vector<int> v = {10,20,30}


否则,您可以拥有一个数据数组,然后使用for循环。
int array[] = {10,20,30}
for(unsigned int i=0; i<sizeof(array)/sizeof(array[0]); i++)
{
     v.push_back(array[i]);
}

除了这些,上面还介绍了使用某些代码的各种其他方式。我认为,这些方式易于记忆且易于编写。

#10 楼

最简单的方法是:

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


评论


哪个编译器?您在这里使用C ++ 11吗?

– Agnel Kurian
13年1月26日在6:23

具有-std = c ++ 0x的g ++ 4.6.3。

– Paul Baltescu
2013年1月28日15:56

#11 楼

我使用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;
}


演示

#12 楼

如果您的编译器支持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))


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

INIT_VECTOR(int, my_vector, {1, 2, 3, 4});


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

#13 楼

如果您不想使用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;
}


评论


我还无法弄清楚如何使用此代码,但看起来很有趣。

–丹尼尔·巴克马斯特(Daniel Buckmaster)
2012年4月3日上午10:06

就像上面的评论之一。只是重载+ =和逗号运算符。为了清楚起见,请加上括号:(((((v + = 1),2),3),4),5)这是这样工作的:首先,vector + = T返回vector_inserter,将其称为vi,它封装了原始向量,然后将vi,T添加到vi封装的原始向量中,然后将其自身返回,以便我们可以再次进行vi,T。

–皮蒂·昂格蒙库尔(Piti Ongmongkolkul)
2012年4月4日在1:10



我认为这段代码在gcc 4.2.1上无法正常工作,因为返回对+ =运算符内部局部变量的引用,但是想法很出色。我编辑了代码,然后出现了另一个副本构造函数。现在是流-> + =-> ctor->逗号->复制-> dtor->逗号......->逗号-> dtor。

– Yevhen
2012年6月13日12:56



我可能会重载<<而不是+ =。至少<<由于位移和cout已经有模糊的副作用规则

– Speed8ump
18年2月23日在18:22

#14 楼

在C ++ 11中:

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


评论


如果您已经在使用C ++ 11,则不妨直接使用-vector arr = {10,20,30};。

– Bernhard Barker
2015年2月24日13:09



实际上,我有一个传入的int [](一些C库),想推送到一个向量中(C ++库)。这个答案有所帮助,其余的没有;-)

–星云
15年7月20日在7:52

#15 楼

您可以使用boost :: assign来做到这一点。

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


详细信息

评论


在很长一段时间内,我还没有看到运营商超负荷滥用的更糟情况。 + =是在1,2,3,4 ..处附加到值的末尾,还是在第1个元素上加1,在第2个元素上加2,在第3个元素上加3(因为这样的语法应在类似MATLAB的语言)

– bobobobo
13年11月9日在20:42



#16 楼

Viktor Sehr对此问题做了一个较新的重复问题。对我而言,它紧凑,外观吸引人(看起来就像您在“推入”值),不需要c ++ 11或第三方模块,并且避免使用额外的(书面)变量。以下是我如何使用它进行一些更改。在以后的界面中,我可能会转向扩展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)


#17 楼

以下方法可用于在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);等等
vector<int>v = {1, 3, 5, 7};

第三个是仅在C ++ 11起允许。

#18 楼

这里有很多很好的答案,但是由于我是在阅读本文之前独立来到我自己的,所以我想无论如何我都会把我扔在这里...
这是我正在为此使用的一种方法在所有编译器和平台上均可通用工作:
创建一个结构或类作为对象集合的容器。为<<定义一个运算符重载函数。
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) );

这样,您可以在一条简单的代码行中生成动态大小的对象集合并将其传递给函数!

#19 楼

如果您希望某些东西与Boost :: assign的通用顺序相同,而又不对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);
}


#20 楼

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>


评论


问题指出C ++ 03(不是11)

– Mike P
2014年9月8日上午9:55

我认为在回答此问题时并没有指定03。虽然记不清了。但是,对于寻求快速解决方案的人来说,它仍然是一个有用的答案。

– shaveenk
2014年9月8日在17:26

#21 楼

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


#22 楼

如果数组是:

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 


#23 楼

在编写测试时在不定义变量的情况下创建矢量内联非常方便,例如:

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


#24 楼

对向量进行硬编码的方式有很多种,我将分享几种方式:


通过逐个推送值进行初始化

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


#25 楼

相关的,如果您想让向量完全准备好进入快速语句(例如,立即传递给另一个函数),则可以使用以下代码:

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


尽管要小心decltype,但要确保第一个值清楚你想要什么。

#26 楼

B. Stroustrup在C ++ 11版本的Prog的第464页的16.2.10自引用中描述了一种链接操作的好方法。郎函数返回引用的地方,此处已修改为向量。这样,您可以像v.pb(1).pb(2).pb(3);一样进行链接,但是对于如此小的增益来说可能工作量很大。


评论


armadillo库执行此操作以进行矩阵初始化,但使用<<操作符代替命名函数:arma.sourceforge.net/docs.html#element_initialisation

– Agnel Kurian
16-2-19在4:31

#27 楼

“如何创建STL矢量并如上所述进行初始化?以最少的打字工作来做到这一点的最佳方法是什么?”
初始化内置控件时,最简单的初始化矢量的方法是数组使用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在执行分配(标记的语句)后大小为3个元素。

评论


在相似的行中,我试图初始化地图std :: map catinfo = {{{1,false}};但是,然后出现此错误错误:在C ++ 98中,“ catinfo”必须由构造函数而不是“ {...}”初始化

–pdk
2013年9月8日7:42



#28 楼

如果您想在自己的课堂上上课:

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


#29 楼

最简单,符合人体工程学的方式(使用C ++ 11或更高版本):
auto my_ints = {1,2,3};