고정 된 (그리고 적은) 수의 값에 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
상수가 아닌 벡터를 사용하는 함수로 전달하기 위해 상수를 제거하는 데 사용 합니다.하지만 알고있는 것은 벡터를 수정하지 않습니다.
후자는 고글을 보는 사람이 고글에 대해 의견을 말하고 아무것도하지 않는다는 사실을 알리는 것 중 하나입니다. 그것은 정확히 무엇 const_cast
을위한 것이지만, 만약 당신이 필요하다면 const_cast
, 당신은 이미 패배 했다는 합리적으로 강력한 주장이 있습니다 .
이 두 가지 작업을 모두 수행하는 것은 (복사 생성자로 상수가 아닌 벡터에서 const 벡터를 만든 다음 상수를 캐스트하는 것) 확실히 잘못된 것입니다. 방금 비 상수 벡터를 사용 했어야합니다. 따라서이 중 하나만 선택하여 수행하십시오.
[ 편집 :vector<T>
과 (와) 의 차이점에 대해 이야기하고 있음을 확인했습니다 const vector<const T>
. 불행히도 STL에서 vector<const T>
와 vector<T>
전혀 관계가없는 유형, 그리고 그들 사이에 변환 할 수있는 유일한 방법은 복사하는 것입니다. 이것은 벡터와 배열의 차이입니다. a는 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;
}
}
답변
다른 사람들이 말했듯이 소스 배열에 대한 포인터를 제공하지 않는 한 C 스타일 배열을 초기화하는 것과 같은 방식으로 벡터를 초기화 할 수 없습니다. 그러나이 경우 벡터가 전역 상수 인 경우 기존 C 스타일 배열을 대신 사용하지 않는 이유는 무엇입니까?
const int MyInts[] = {
1, 2, 3, 4, 5};
const size_t NumMyInts = sizeof(MyInts)/sizeof(MyInts[0]);
const 벡터에 대해 알고리즘을 사용하는 것과 같은 방식으로이 배열에 대해 STL 알고리즘을 사용할 수도 있습니다.
const int* myInt = std::find( &MyInts[0], &MyInts[NumMyInts], 3);
답변
두 단계로 수행 할 수 있습니다.
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])));
}
아마도 당신이 좋아하는 것만 큼 아름답지는 않지만 기능적입니다.
답변
어때 :
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;
}