简体   繁体   English

如何初始化 &#39;const std::vector<T> &#39; 像交流数组

[英]how-to initialize 'const std::vector<T>' like a c array

Is there an elegant way to create and initialize a const std::vector<const T> like const T a[] = { ... } to a fixed (and small) number of values?有没有一种优雅的方法来创建和初始化一个const std::vector<const T>const T a[] = { ... }到固定(和小)数量的值?
I need to call a function frequently which expects a vector<T> , but these values will never change in my case.我需要经常调用一个需要vector<T>的函数,但这些值在我的情况下永远不会改变。

In principle I thought of something like原则上我想到了类似的东西

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

since v won't be used outside of this compilation unit.因为 v 不会在这个编译单元之外使用。

You either have to wait for C++0x or use something likeBoost.Assign to do that.您要么必须等待 C++0x,要么使用Boost.Assign 之类的东西来做到这一点。

eg:例如:

#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:对于 C++11:

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

If you're asking how to initialise a const vector so that it has interesting contents, then the answer is probably to use the copy constructor.如果您问如何初始化 const 向量以使其具有有趣的内容,那么答案可能是使用复制构造函数。 First you laboriously fill in a vector, then you create your new const vector from it.首先,您费力地填充一个向量,然后从中创建新的 const 向量。 Or you can use the vector<InputIterator>(InputIterator, InputIterator) constructor template to initialise from some other kind of container or an array.或者,您可以使用vector<InputIterator>(InputIterator, InputIterator)构造函数模板从某种其他类型的容器或数组进行初始化。 If an array, then that could have been defined with an initialisation list.如果是数组,则可以使用初始化列表定义它。

Something like this is hopefully close to what you want:像这样的东西希望接近你想要的:

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

If you're asking how to pass a const vector into a function which takes a vector then the answer is either:如果您要问如何将常量向量传递给采用向量的函数,那么答案是:

  • you can't, because the function might alter the vector and your object/reference is const.你不能,因为函数可能会改变向量,而你的对象/引用是常量。 Make a non-const copy of the original, and pass that in.制作原始文件的非常量副本,然后将其传入。

or或者

  • use const_cast to remove the constness in order to pass it into a function which takes a non-const vector but which you just so happen to know will not modify the vector.使用const_cast删除常量,以便将其传递给一个函数,该函数采用非常量向量,但您碰巧知道它不会修改向量。

The latter is one of those things which will, quite rightly, cause anyone who sees it to make comments about goggles, and the fact that they do nothing.后者是其中之一,完全正确地会导致任何看到它的人对护目镜发表评论,以及他们什么都不做的事实。 It's exactly what const_cast is for, but there's a reasonably strong argument that says if you need const_cast , you have already lost.这正是const_cast的用途,但有一个相当有力的论据表明,如果您需要const_cast ,那么您已经输了。

Doing both of those things (creating a const vector from a non-const one with the copy constructor, and then casting away constness) is definitely wrong - you should have just used a non-const vector.做这两件事(使用复制构造函数从非常量向量创建一个常量向量,然后抛弃常量)绝对是错误的——你应该只使用一个非常量向量。 So pick at most one of these to do...所以最多选择其中一个来做......

[ Edit: just noticed that you're talking about a difference between vector<T> and const vector<const T> . [编辑:刚刚注意到你在谈论vector<T>const vector<const T>之间的区别。 Unfortunately in the STL, vector<const T> and vector<T> are completely unrelated types, and the only way to convert between them is by copying.不幸的是,在 STL 中, vector<const T>vector<T>是完全不相关的类型,在它们之间进行转换的唯一方法是通过复制。 This is a difference between vectors and arrays - a T** can be silently and safely converted to const T *const * ]这是向量和数组之间的区别 - T**可以静默且安全地转换为const T *const * ]

Short and dirty way (similar to Boost's list_of() )简短而肮脏的方式(类似于 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"));
}

Now, C++11 has initializer lists, so you don't need to do it that way or even use Boost.现在,C++11 有初始化列表,所以你不需要那样做,甚至不需要使用 Boost。 But, as an example, you can do the above in C++11 more efficiently like this:但是,例如,您可以像这样在 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;
        }
    }

But, it's still not as efficient as using a C++11 initializer list because there's no operator=(vlist_of&&) defined for vector.但是,它仍然不如使用 C++11 初始值设定项列表有效,因为没有为向量定义operator=(vlist_of&&)

tjohns20's way modified like the following might be a better c++11 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;
    }
    
}

As others have said, you can't init a vector the same way you can init a C-style array, unless you give it pointers to a source array.正如其他人所说,你不能像初始化一个 C 风格的数组一样初始化一个向量,除非你给它一个指向源数组的指针。 But in that case, if your vector is a global const, why not just use an old C-style array instead?但是在那种情况下,如果您的向量是全局常量,为什么不使用旧的 C 样式数组呢?

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

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

You can even use STL algorithms against this array, the same way you would use algorithms against a const vector...您甚至可以对这个数组使用 STL 算法,就像对 const 向量使用算法一样......

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

You can do it in two steps:您可以分两步完成:

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

Perhaps not as beautiful as you might like, but functional.也许没有你喜欢的那么漂亮,但实用。

How about:怎么样:

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

Old question, but I ran into the same issue today, here's the approach that was most acceptable for my purposes:老问题,但我今天遇到了同样的问题,这是我的目的最可接受的方法:

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

Example to avoid excessive copying:避免过度复制的示例:

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

Not sure if I understood you right.不确定我是否理解你的意思。 I understand your question like this: you want to initialize a vector to a large number of elements.我理解你的问题是这样的:你想将一个向量初始化为大量元素。 What's wrong with using push_back() on the vector?在向量上使用push_back()有什么问题? :-) :-)

If you know the number of elements to be stored (or are sure that it will store less than the next power of 2) you can do this, if you have a vector of pointers of type X (works only with pointers):如果您知道要存储的元素数量(或确定它会存储小于 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];

Beware of adding more than the next power of 2 elements, even if using push_back() .即使使用push_back() ,也要注意添加超过 2 的下一个幂的元素。 Pointers to v.begin() will then be invalid.指向v.begin()指针将无效。

If they're all the same you can just do如果他们都一样,你可以做

vector<T> vec(num_items, item);

but I assume they're not - in which case the neatest way is probably:但我认为它们不是 - 在这种情况下,最简洁的方法可能是:

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

C++0x will let you use an initialiser list in exactly the way you're thinking of, but that's not a lot of good right now, unfortunately. C++0x 将让您完全按照您的想法使用初始化列表,但不幸的是,现在这不是很好。

Based on Shadow2531's response, I'm using this class to initialise vectors, without actually inheriting from std::vector like Shadow's solution did基于 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;
};

Usage:用法:

std::vector<int> testVec = vector_init<int>(1)(2)(3)(4)(5).end();

Compared to Steve Jessop's solution it creates a lot more code, but if the array creation isn't performance critical I find it a nice way to initialise an array in a single line与 Steve Jessop 的解决方案相比,它创建了更多的代码,但如果数组创建不是性能关键,我发现这是在一行中初始化数组的好方法

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何返回const std :: vector <Object *const> ? - How-to return a const std::vector<Object *const>? 如何在旧 C++ 中初始化 const std 向量? - How to initialize a const std vector in old c++? 如何初始化std :: vector数组? - how to initialize an array of std::vector? 如何使用C ++数组初始化OpenCL const向量? [主办] - How to initialize OpenCL const vector with C++ array? [Host] 如何从 C 样式数组初始化 std::vector? - How to initialize std::vector from C-style array? 如何使用std :: array构造函数参数C ++列表初始化const std :: array成员 - How to list-initialize a const std::array member using a std::array constructor argument C++ C ++ std:vector &lt;T * const&gt; - C++ std:vector< T* const> 如何在 C++ 初始值设定项列表中将常量引用成员初始化为另一个成员(标准向量) - How to initialize a const reference member to another member (std vector) in C++ initializer list 如何初始化 std::span<const t*> ? 常量问题</const> - How to initialize std::span<const T*>? Problems with const-ness 如何使用 C++ 中的原语初始化 class(如从 const char* 初始化的 std::string) - How to initialize a class with a primitive in C++(like std::string initialized from const char*)
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM