有没有一种优雅的方法来创建和初始化const std::vector<const T>
类似const T a[] = { ... }
的固定数目(很少)的值?
我需要经常调用一个期望vector<T>
,但是在我的情况下,这些值永远不会改变。
原则上我想到了类似
namespace {
const std::vector<const T> v(??);
}
因为v不会在此编译单元之外使用。
Answers:
您要么必须等待C ++ 0x,要么使用Boost.Assign之类的工具来执行此操作。
例如:
#include <boost/assign/std/vector.hpp>
using namespace boost::assign; // bring 'operator+=()' into scope
vector<int> v;
v += 1,2,3,4,5;
对于C ++ 11:
vector<int> luggage_combo = { 1, 2, 3, 4, 5 };
如果您问如何初始化const向量,使其具有有趣的内容,那么答案可能是使用复制构造函数。首先,您费力地填写一个向量,然后从中创建新的const向量。或者,您可以使用vector<InputIterator>(InputIterator, InputIterator)
构造函数模板从其他某种容器或数组初始化。如果是数组,则可以使用初始化列表进行定义。
希望这样的事情接近您想要的东西:
const T ra[3] = {t1, t2, t3};
const vector<const T> v(ra, ra+3);
如果您问如何将const向量传递给采用向量的函数,那么答案是:
要么
const_cast
去除常量性,以便将其传递到它接受一个非const载体,但你只是这么碰巧知道会不会修改向量的功能。后者是其中的一件事情,很正确的做法是,使任何看到它的人对护目镜发表评论,而事实是他们什么也不做。这正是const_cast
目的,但是有一个合理的论据说,如果您需要const_cast
,您已经迷路了。
做到这两种事情(使用复制构造函数从非常量对象创建一个常量向量,然后丢弃常量)绝对是错误的-您应该只使用了非常量向量。因此,最多选择其中一项来做...
[编辑:只注意到你在谈论之间的差异vector<T>
和const vector<const T>
。不幸的是在STL,vector<const T>
并且vector<T>
是完全无关的类型,并在它们之间转换的唯一方法是通过复制。向量和数组之间的区别-aT**
可以无声且安全地转换为const T *const *
]
简短而肮脏的方式(类似于Boost的list_of()
)
#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>
using namespace std;
template <typename T>
struct vlist_of : public vector<T> {
vlist_of(const T& t) {
(*this)(t);
}
vlist_of& operator()(const T& t) {
this->push_back(t);
return *this;
}
};
int main() {
const vector<int> v = vlist_of<int>(1)(2)(3)(4)(5);
copy(v.begin(), v.end(), ostream_iterator<int>(cout, "\n"));
}
现在,C ++ 11具有初始化程序列表,因此您不需要那样做,甚至不需要使用Boost。但是,作为示例,您可以像这样在C ++ 11中更有效地执行上述操作:
#include <iostream>
#include <vector>
#include <utility>
#include <ostream>
using namespace std;
template <typename T>
struct vlist_of : public vector<T> {
vlist_of(T&& t) {
(*this)(move(t));
}
vlist_of& operator()(T&& t) {
this->push_back(move(t));
return *this;
}
};
int main() {
const vector<int> v = vlist_of<int>(1)(2)(3)(4)(5);
for (const auto& i: v) {
cout << i << endl;
}
}
但是,它仍然没有使用C ++ 11初始化程序列表有效,因为没有operator=(vlist_of&&)
为vector定义。
tjohns20的如下修改方式可能是更好的c ++ 11 vlist_of
:
#include <iostream>
#include <vector>
#include <utility>
using namespace std;
template <typename T>
class vlist_of {
public:
vlist_of(T&& r) {
(*this)(move(r));
}
vlist_of& operator()(T&& r) {
v.push_back(move(r));
return *this;
}
vector<T>&& operator()() {
return move(v);
}
private:
vector<T> v;
};
int main() {
const auto v = vlist_of<int>(1)(2)(3)(4)(5)();
for (const auto& i : v) {
cout << i << endl;
}
}
就像其他人所说的那样,除非您将向量指针指向源数组,否则不能像初始化C样式数组那样初始化向量。但是在这种情况下,如果向量是全局const,为什么不只使用旧的C样式数组呢?
const int MyInts[] = {
1, 2, 3, 4, 5};
const size_t NumMyInts = sizeof(MyInts)/sizeof(MyInts[0]);
您甚至可以针对此数组使用STL算法,就像针对const向量使用算法一样。
const int* myInt = std::find( &MyInts[0], &MyInts[NumMyInts], 3);
这是个老问题,但今天我遇到了同样的问题,这是我所接受的最可接受的方法:
vector<int> initVector(void)
{
vector<int> initializer;
initializer.push_back(10);
initializer.push_back(13);
initializer.push_back(3);
return intializer;
}
int main()
{
const vector<int> a = initVector();
return 0;
}
避免过度复制的示例:
vector<int> & initVector(void)
{
static vector<int> initializer;
if(initializer.empty())
{
initializer.push_back(10);
initializer.push_back(13);
initializer.push_back(3);
}
return intializer;
}
int main()
{
const vector<int> & a = initVector();
return 0;
}
基于Shadow2531的响应,我正在使用此类初始化向量,而没有像Shadow的解决方案那样实际上从std :: vector继承
template <typename T>
class vector_init
{
public:
vector_init(const T& val)
{
vec.push_back(val);
}
inline vector_init& operator()(T val)
{
vec.push_back(val);
return *this;
}
inline std::vector<T> end()
{
return vec;
}
private:
std::vector<T> vec;
};
用法:
std::vector<int> testVec = vector_init<int>(1)(2)(3)(4)(5).end();
与史蒂夫·杰索普(Steve Jessop)的解决方案相比,它创建了更多的代码,但是如果数组的创建对性能没有要求,我发现这是在一行中初始化数组的好方法
不知道我是否理解正确。我理解您的问题是这样的:您想将向量初始化为大量元素。push_back()
在向量上使用怎么了?:-)
如果您知道要存储的元素数量(或确保它存储的下一个2的次幂),则可以执行此操作,前提是您拥有一个向量类型为X的指针(仅适用于指针):
std::vector< X* > v;
v.reserve(num_elems);
X* p = v.begin();
for (int count = 0; count < num_elems; count++)
p[count] = some_source[count];
请注意,即使使用,也要添加2个元素的下一个幂push_back()
。指向的指针v.begin()
将无效。