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

What is the easiest way to initialize a std::vector with hardcoded elements?

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

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

我如何创建一个std::vector并初始化它,同样优雅?

我知道最好的方法是:

1
2
3
4
5
std::vector<int> ints;

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

有更好的方法吗?


如果你的编译器支持C++ 11,你可以简单地做:

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

从4.4版起在GCC中提供。不幸的是,VC++2010在这方面似乎落后了。

或者,boost.assign库使用非宏魔术允许以下操作:

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

或:

1
2
3
4
5
#include <boost/assign/std/vector.hpp>
using namespace boost::assign;
...
std::vector<int> v;
v += 1, 2, 3, 4;

但请记住,这有一些开销(基本上,list_of在引擎盖下构造一个std::deque,所以对于性能关键的代码,您最好像yacoby所说的那样做。


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

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


在C++0x中,您将能够以与数组相同的方式来完成它,但不能在当前标准中执行。

只有语言支持才能使用:

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

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

1
vector<int> v = list_of(10)(20)(30);

要避免硬编码数组的大小,请执行以下操作:

1
2
3
4
5
6
7
8
9
10
11
12
// 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))


(P)如果你能,用现代C+[11,14,17,…]方式:(p)字母名称(P)The old way of looping over a variable-Length array or using EDOCX1 commercial 4-is truly terrible on the eyes and completely unnecessary in terms of mental overhead.Yuck.(p)


在C++ 11中:

1
2
3
4
5
6
#include <vector>
using std::vector;
...
vector<int> vec1 { 10, 20, 30 };
// or
vector<int> vec2 = { 10, 20, 30 };

使用以下增强列表:

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

使用增强分配:

1
2
3
4
5
6
#include <vector>
#include <boost/assign/std/vector.hpp>
using std::vector;
...
vector<int> vec;
vec += 10, 20, 30;

传统STL:

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

带通用宏的传统STL:

1
2
3
4
5
6
7
#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:

1
2
3
4
5
6
#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);


我只是想把我的0.02美元投进去。我倾向于声明:

1
2
3
4
5
template< typename T, size_t N >
std::vector<T> makeVector( const T (&data)[N] )
{
    return std::vector<T>(data, data+N);
}

在某个实用程序头中,需要的只是:

1
2
const double values[] = { 2.0, 1.0, 42.0, -7 };
std::vector<double> array = makeVector(values);

但是我不能等待C++0X。我被困了,因为我的代码也必须在VisualStudio中编译。喝倒采。


(P)before C++11:(p)(P)方法1=(p)字母名称(P)方法2=(p)字母名称(P)C++11 onward below is also possible(p)字母名称


从:

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

如果你没有一个C++ 11编译器,那么你就不想使用Booost:

1
2
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编译器,可以使用Booost:

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

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

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

最简单的方法是:

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


(P)For vector initialisation-(p)字母名称(P)如果你有C++11竞争对手,你可以成为礼物。(p)(P)Else,you can have an array of the data and they use a for loop.(p)字母名称(P)Apart from these,there are various other ways described above using some code.在我看来,这些方式很容易记起来,而且很容易写下来。(p)


如果编译器支持variadic宏(对于大多数现代编译器都是如此),则可以使用以下宏将矢量初始化转换为一行程序:

1
2
3
#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))

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

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

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


如果你不想使用boost,但想享受类似于

1
2
std::vector<int> v;
v+=1,2,3,4,5;

只包括这段代码

1
2
3
4
5
6
7
8
9
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;
}


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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#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;
}

演示


在C++ 11中:

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


最近的一个重复的问题得到了维克多·瑟尔的回答。对我来说,它是紧凑的、视觉上吸引人的(看起来像是在推挤值),不需要C++ 11或第三方模块,并且避免使用额外的(书面的)变量。下面是我如何使用它并做一些更改。我可以在以后的集成中切换到扩展向量和/或va_arg的函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// 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)

您可以使用boost::assign来实现这一点。

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

这里详细


(P)Below methods can be used to initialize the vector in C++。(p)

  • (P)字母名称(p)
  • (P)字母名称(p)
  • (P)字母名称(p)
  • (P)The third one is allowed only in C++11 onwards.(p)


    (P)有一个很好的答案在这里,但自从我独立地来到我自己的地方之前,我figured I'd toss mine up here anyway…(p)(P)这里的一种方法是,我将使用这一方法,这将是一个普遍性的工作,参加者和平台:(p)(P)创建一个结构或类别作为一个容器,以收集你的目标。定义一个超值操作函数。(p)字母名称(P)You can create functions which take your structure as a parameter,e.g.:(p)字母名称(P)Then,you can call that function,like this:(p)字母名称(P)That way,you can build and pass a dynamically sized collection of objects to a function in one single clean line!(p)


    如果需要与boost::assign具有相同常规顺序的内容,而不创建对boost的依赖关系,则以下内容至少类似:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    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);
    }

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

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


    字母名称


    (P)If the array is:(p)字母名称


    1
    2
    3
    typedef std::vector<int> arr;

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

    编译使用:

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


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

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

    示例函数

    1
    2
    3
    4
    5
    6
    template<typename T>
    void test(std::vector<T>& values)
    {
        for(T value : values)
            std::cout<<value<<std::endl;
    }

    例用

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

    尽管要注意decltype,但要确保第一个值是您想要的。


    "如何创建一个STL向量并像上面那样初始化它?用最少的打字工作量,最好的方法是什么?"

    初始化初始化数组时最简单的方法是使用在C++ 11中引入的初始化列表。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    // 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个元素。


    (P)b.Stroustrup describines 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.这个方法你可以像EDOCX1一样,发音0,但它可能是太多的工作为这些小的性别。(p)字母名称布尔奇1