如何初始化'const std :: vector <t>'就像一个c数组</t>

时间:2008-10-23 20:55:00

标签: c++ stl

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

原则上我想到了像

这样的东西
{{1}}

因为v不会在此编译单元之外使用。

10 个答案:

答案 0 :(得分:60)

您必须等待C ++ 0x或使用类似Boost.Assign的内容来执行此操作。

e.g:

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

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

for C ++ 11:

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

答案 1 :(得分:39)

如果您正在询问如何初始化const向量以使其具有有趣的内容,那么答案可能是使用复制构造函数。首先,你费力地填充一个向量,然后从中创建新的const向量。或者,您可以使用向量&lt; InputIterator&gt;(InputIterator,InputIterator)构造函数模板从其他类型的容器或数组初始化。如果是数组,则可以使用初始化列表定义。

这样的事情有希望接近你想要的东西:

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

如果你问如何将const向量传递给一个带向量的函数,那么答案就是:

  • 你不能,因为函数可能会改变向量而你的对象/引用是const。制作原件的非常量副本,然后传入。

  • 使用const_cast删除常量,以便将它传递给一个带有非常量向量的函数,但是你恰好知道它不会修改向量。

后者是其中一项非常正确的事情,会使任何看到它的人对护目镜发表评论,以及他们什么也不做。这正是const_cast的用途,但是有一个相当强大的论据说,如果你需要const_cast,你已经输了。

做这两件事(用复制构造函数创建一个非const的const向量,然后抛弃const)绝对是错误的 - 你应该只使用一个非const向量。所以最多选择其中一个做...

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

答案 2 :(得分:15)

短而脏的方式(类似于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初始化列表那样有效,因为没有为vector定义operator =(vlist_of&amp;&amp;)。

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

}

答案 3 :(得分:12)

正如其他人所说,你不能像初始化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);

答案 4 :(得分:6)

您可以分两步完成:

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

也许不像你想的那么美丽,但功能性。

答案 5 :(得分:5)

怎么样:

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

答案 6 :(得分: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;
}

答案 7 :(得分:0)

不确定我是否理解你。我理解你的问题:你想要将一个向量初始化为大量的元素。在向量上使用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()的指针将无效。

答案 8 :(得分:0)

如果它们完全一样,你可以做到

vector<T> vec(num_items, item);

但我认为他们不是 - 在这种情况下最好的方式可能是:

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

C ++ 0x将允许您完全按照您的想法使用初始化列表,但那就是 不幸的是,现在不是很好。

答案 9 :(得分: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的解决方案相比,它创建了更多的代码,但如果数组创建不是性能关键的,我发现它是一种在单行中初始化数组的好方法