如何初始化 'const std::vector' 像交流阵列

发布于 2024-07-07 10:04:38 字数 333 浏览 4 评论 0原文

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

原则上我想到了类似的东西,

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

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

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?
I need to call a function frequently which expects a vector<T>, but these values will never change in my case.

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

当梦初醒 2024-07-14 10:04:38

对于 C++11:

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

原始答案:

您要么必须等待 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;

For C++11:

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

Original answer:

You would either have to wait for C++0x or use something like Boost.Assign to do that.

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;
樱娆 2024-07-14 10:04:38

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

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

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

如果你问如何将 const 向量传递到接受向量的函数中,那么答案是:

  • 你不能,因为该函数可能会改变向量和你的对象/reference 是常量。 制作原始副本的非常量副本,然后将其传入。

或者

  • 使用 const_cast 删除常量,以便将其传递到采用非常量向量的函数中,但您恰好碰巧发生了知道不会修改向量。

后者是其中之一,很正确地,任何看到它的人都会对护目镜发表评论,而且事实上它们什么也没做。 这正是 const_cast 的用途,但有一个相当有力的论据表明,如果您需要 const_cast ,那么您就已经失败了。

做这两件事(使用复制构造函数从非常量向量创建一个常量向量,然后抛弃常量性)绝对是错误的 - 你应该只使用一个非常量向量。 因此,最多选择其中一项来执行...

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

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. First you laboriously fill in a vector, then you create your new const vector from it. Or you can use the vector<InputIterator>(InputIterator, InputIterator) constructor template to initialise from some other kind of container or an array. 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.

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.

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>. 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. This is a difference between vectors and arrays - a T** can be silently and safely converted to const T *const *]

花心好男孩 2024-07-14 10:04:38

简短而肮脏的方式(类似于 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;
    }
    
}

Short and dirty way (similar to Boost's 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. But, as an example, you can do the above in C++11 more efficiently like this:

    #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.

tjohns20's way modified like the following might be a better 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;
    }
    
}
慕烟庭风 2024-07-14 10:04:38

正如其他人所说,您不能像初始化 C 样式数组那样初始化向量,除非您为其提供指向源数组的指针。 但在这种情况下,如果您的向量是全局常量,为什么不直接使用旧的 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);

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. But in that case, if your vector is a global const, why not just use an old C-style array instead?

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...

const int* myInt = std::find( &MyInts[0], &MyInts[NumMyInts], 3);
地狱即天堂 2024-07-14 10:04:38

您可以分两步完成:

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

也许不像您想要的那么漂亮,但很实用。

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.

不奢求什么 2024-07-14 10:04:38

怎么样:

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

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);
沧桑㈠ 2024-07-14 10:04:38

老问题,但我今天遇到了同样的问题,这是最适合我的目的的方法:

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

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;
}
南巷近海 2024-07-14 10:04:38

如果它们都是相同的,你可以这样做

vector<T> vec(num_items, item);

,但我假设它们不是 - 在这种情况下,最简洁的方法可能是:

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

C++0x 将让你以你想要的方式使用初始化列表,但是那是
不幸的是,现在没有太多好处。

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.

说好的呢 2024-07-14 10:04:38

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

Based on Shadow2531's response, I'm using this class to initialise vectors, without actually inheriting from std::vector like Shadow's solution did

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

烟酉 2024-07-14 10:04:38

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

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? :-)

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):

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(). Pointers to v.begin() will then be invalid.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文