我可以创建一个数组并像这样初始化它:
int a[] = {10, 20, 30};
如何创建一个std::vector
并优雅地对其进行初始化?
我知道的最好方法是:
std::vector<int> ints;
ints.push_back(10);
ints.push_back(20);
ints.push_back(30);
有没有更好的办法?
tr1::array
之所以有用,是因为普通数组不提供STL容器的接口
我可以创建一个数组并像这样初始化它:
int a[] = {10, 20, 30};
如何创建一个std::vector
并优雅地对其进行初始化?
我知道的最好方法是:
std::vector<int> ints;
ints.push_back(10);
ints.push_back(20);
ints.push_back(30);
有没有更好的办法?
tr1::array
之所以有用,是因为普通数组不提供STL容器的接口
Answers:
一种方法是使用数组初始化向量
static const int arr[] = {16,2,77,29};
vector<int> vec (arr, arr + sizeof(arr) / sizeof(arr[0]) );
static
或const
,它将正常工作,但是它们都使它在使用方式上更加明确,并允许编译器进行其他优化。
如果您的编译器支持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 = {};
?
std::vector<T> vector;
如果可以,请使用现代的C ++ [11,14,17,...]方法:
std::vector<int> vec = {10,20,30};
在可变长度数组上循环或使用的旧方法sizeof()
在眼睛上确实很可怕,就精神上的负担而言完全没有必要。uck
在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))
int another[size_of_array(array)]
,而您却可以做到int another[ARRAY_SIZE(array)]
。
sizeof
不需要定义的表达式外,我们实际上不需要该函数。尽管您实际上可以提供一个定义,但是要正确地执行定义,则需要静态分配数组并返回对其的引用,接下来的问题是什么是数组的值?(还要注意,这意味着该函数实例化的每个类型/大小组合只有一个数组!)由于对它没有明智的用法,所以我宁愿避免使用它。
在C ++ 11中:
#include <vector>
using std::vector;
...
vector<int> vec1 { 10, 20, 30 };
// or
vector<int> vec2 = { 10, 20, 30 };
使用boost 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]) );
具有通用宏的常规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);
std::begin
和std::end
用于数组,因此向量也可以像一样初始化static const int arr[] = {10,20,30}; vector<int> vec(begin(arr), end(arr));
。
只是以为我会扔掉我的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中编译。嘘
const T (&data)[N]
吗?如何在调用中推导出数组的大小makeVector(values)
?
从...开始:
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};
最简单的方法是:
vector<int> ints = {10, 20, 30};
我使用构建自己的解决方案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;
}
如果您的编译器支持可变参数宏(大多数现代编译器都适用),则可以使用以下宏将向量初始化转换为单行代码:
#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的int新向量,其元素为1,2,3,4。
如果您不想使用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;
}
((((v+=1),2),3),4),5)
,请vector<T> += T
加上括号:这是它的工作原理:首先,返回一个vector_inserter调用它vi
来封装原始向量,然后vi,T
将T添加到vi
封装并返回自身的原始向量中,以便我们vi,T
再次执行。
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)
这里有很多很好的答案,但是由于我在阅读本文之前是独立到达我自己的,所以我认为无论如何我都会把我扔在这里...
这是我正在使用的一种方法,它将在编译器和平台之间通用:
创建一个结构或类作为对象集合的容器。为<<定义一个运算符重载函数。
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) );
这样,您可以在一条简单的代码行中生成动态大小的对象集合并将其传递给函数!
如果您希望某些东西与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);
}
虽然我希望使用它的语法更简洁,但仍然不是特别糟糕:
std::vector<int> x = (makeVect(1), 2, 3, 4);
// 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.
在编写测试时创建向量内联而不定义变量非常方便,例如:
assert(MyFunction() == std::vector<int>{1, 3, 4}); // <- this.
相关的,如果您想让向量完全准备好进入快速语句(例如,立即传递给另一个函数),则可以使用以下代码:
#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,但要确保第一个值显然是您想要的。
“如何创建一个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个元素。
B. Stroustrup 在Prog的C ++ 11版本的第464页的16.2.10自引用中描述了一种链接操作的好方法。郎 函数返回引用的地方,此处已修改为向量。这样您就可以像这样串连起来,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
有多种方法可以对向量进行硬编码,我将分享几种方法:
// 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());