development

'const std :: vector 초기화 방법

big-blog 2020. 10. 12. 07:47
반응형

'const std :: vector 초기화 방법'AC 어레이와 유사


고정 된 (그리고 적은) 수의 값에 const std::vector<const T>좋아요 를 만들고 초기화하는 우아한 방법이 const T a[] = { ... }있습니까?
를 예상하는 함수를 자주 호출해야 vector<T>하지만이 값은 제 경우에는 절대 변경되지 않습니다.

원칙적으로 나는 다음과 같은 것을 생각했다.

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

v는이 컴파일 단위 외부에서 사용되지 않기 때문입니다.


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이기 때문에 할 수 없습니다. 원본의 상수가 아닌 복사본을 만들어 전달합니다.

또는

  • const_cast를 사용하여 상수가 아닌 벡터를 사용하지만 벡터를 수정하지 않는 함수로 전달하기 위해 constness를 제거하십시오.

후자는 고글을 보는 사람이 고글에 대해 의견을 말하고 아무것도하지 않는다는 사실을 알리는 것 중 하나입니다. 그것은 정확히 const_cast의 목적이지만, const_cast가 필요하다면 이미 잃어버린 것이라고 말하는 합리적으로 강력한 주장이 있습니다.

이 두 가지 작업을 모두 수행하는 것은 (복사 생성자로 상수가 아닌 벡터에서 const 벡터를 만든 다음 상수를 캐스트하는 것) 확실히 잘못된 것입니다. 방금 비 상수 벡터를 사용 했어야합니다. 그러니이 중 하나만 선택하십시오 ...

[편집 : 방금 vector <T>와 const vector <const T>의 차이점에 대해 이야기하고 있다는 것을 알았습니다. 불행히도 STL에서 vector <const T>와 vector <T>는 완전히 관련이없는 유형이며 둘 사이를 변환하는 유일한 방법은 복사하는 것입니다. 이것은 벡터와 배열의 차이입니다. T **는 조용하고 안전하게 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;
    }
}

그러나 벡터에 대해 정의 된 operator = (vlist_of &&)가 없기 때문에 C ++ 11 이니셜 라이저 목록을 사용하는 것만 큼 효율적이지 않습니다.

다음과 같이 수정 된 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. 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);

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

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.


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.


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

참고URL : https://stackoverflow.com/questions/231491/how-to-initialize-const-stdvectort-like-a-c-array

반응형