如何像 c 数组一样初始化‘ const std: : Vector < T >’

有没有一种优雅的方法来创建和初始化像 const T a[] = { ... }这样的 const std::vector<const T>到一个固定(和小)数量的值?
我需要经常调用一个需要 vector<T>的函数,但是这些值在我的情况下永远不会改变。

原则上我想到的是

namespace {
const std::vector<const T> v(??);
}

因为 v 不能在这个编译单元之外使用。

97386 次浏览

对于 C + + 11:

vector<int> luggage_combo = { 1, 2, 3, 4, 5 };

原答案:

您可能需要等待 C + + 0x 或者使用类似 推进,分配的工具来完成这项工作。

例如:

#include <boost/assign/std/vector.hpp>
using namespace boost::assign; // bring 'operator+=()' into scope


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

如果你想知道如何初始化一个 const 向量,使其具有有趣的内容,那么答案很可能是使用复制建构子。首先您要费力地填充一个向量,然后从它创建新的常量向量。或者您可以使用 vector<InputIterator>(InputIterator, InputIterator)构造函数模板从其他类型的容器或数组进行初始化。如果是一个数组,那么可以用初始化列表来定义它。

希望这样的东西能接近你想要的:

const T ra[3] = {t1, t2, t3};
const vector<const T> v(ra, ra+3);

如果你想知道如何将一个常量向量传递给一个带有向量的函数,那么答案是:

  • 不能,因为函数可能会改变向量,而你的对象/引用是 const。制作原始文件的非常数副本,并将其传递进去。

或者

  • 使用 const_cast去除常量,以便将其传递给一个函数,该函数接受一个非常量向量,但你碰巧知道它不会修改向量。

后者是那些事情之一,这将是相当正确的,导致任何人看到它作出评论的护目镜,事实上,他们什么也不做。这正是 const_cast的用途,但是有一个相当有力的论点说,如果你需要 const_cast,你已经输了。

做这两件事(用复制建构子从非常量向量创建一个常量向量,然后抛弃常量)绝对是错误的——你应该直接使用非常量向量。所以最多选择其中一个来做..。

[ 编辑:刚刚注意到你在谈论 vector<T>const vector<const T>之间的区别。不幸的是,在 STL 中,vector<const T>vector<T>是完全不相关的类型,在它们之间转换的唯一方法是复制。这是向量和数组之间的区别-一个 T**可以静默地安全地转换为 const T *const *]

正如其他人所说,你不能像初始化 C 风格的数组那样初始化一个向量,除非你给它指向一个源数组。但是在这种情况下,如果向量是全局常量,为什么不使用一个旧的 C 样式的数组呢?

const int MyInts[] = {
1, 2, 3, 4, 5};


const size_t NumMyInts = sizeof(MyInts)/sizeof(MyInts[0]);

你甚至可以对这个数组使用 STL 算法,就像你对常量矢量使用算法一样..。

const int* myInt = std::find( &MyInts[0], &MyInts[NumMyInts], 3);

不知道我理解得对不对。我理解您的问题是这样的: 您希望将向量初始化为大量元素。在矢量上使用 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];

即使使用 push_back(),也要小心添加超过2个元素的下一次幂的元素。指向 v.begin()的指针将无效。

你可以分两步来做:

namespace {
const T s_actual_array[] = { ... };
const std::vector<const T> s_blah(s_actual_array,
s_actual_array + (sizeof(s_actual_array) / sizeof(s_actual_array[0])));
}

也许没有你想的那么漂亮,但是很实用。

如果他们都是一样的,你可以直接做

vector<T> vec(num_items, item);

但我认为他们不是——在这种情况下,最简单的方法可能是:

vector<T> vec(num_items);
vec[0] = 15;
vec[1] = 5;
...

C + + 0x 允许您按照您所想的方式使用初始值设定项列表,但是 不幸的是,现在没什么好消息。

短而肮脏的方式(类似于 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&&)

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

}

基于 Shadow2531的响应,我使用这个类来初始化向量,而不像 Shadow 的解决方案那样实际继承 std: : 向量

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 的解决方案相比,它创建了更多的代码,但是如果数组创建不是性能关键,我发现它是一个很好的方法,可以在一行中初始化一个数组

这个怎么样:

int ar[]={1,2,3,4,5,6};
const int TotalItems = sizeof(ar)/sizeof(ar[0]);
std::vector<int> v(ar, ar+TotalItems);

老问题了,但我今天遇到了同样的问题,这里有一个方法,对我的目的来说是最可以接受的:

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