как инициализировать ‘const std :: vector ‘ как ac array

Есть ли элегантный способ создания и инициализации const std::vector например const T a[] = { ... } к фиксированному (и небольшому) числу значений?
Мне нужно часто вызывать функцию, которая ожидает vector , но эти значения никогда не изменятся в моем случае.

В принципе я думал о чем-то вроде

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

так как v не будет использоваться вне этой единицы компиляции.

Вы либо должны ждать C ++ 0x, либо использовать что-то вроде Boost.Assign для этого.

например:

 #include  using namespace boost::assign; // bring 'operator+=()' into scope vector v; v += 1,2,3,4,5; 

для C ++ 11:

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

Если вы спросите, как инициализировать вектор const, чтобы он имел интересное содержимое, тогда, вероятно, ответ должен использовать конструктор копирования. Сначала вы трудоемко заполняете вектор, затем вы создаете из него свой новый вектор const. Или вы можете использовать шаблон конструктора vector (InputIterator, InputIterator) для инициализации из другого типа контейнера или массива. Если массив, то это можно было бы определить с помощью списка инициализации.

Что-то вроде этого, надеюсь, близко к тому, что вы хотите:

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

Если вы спрашиваете, как передать вектор const в функцию, которая принимает вектор, тогда ответ будет либо:

  • вы не можете, потому что функция может изменить вектор, а ваш объект / ссылка – const. Сделайте неконстантную копию оригинала и передайте это.

или

  • используйте const_cast для удаления константы, чтобы передать ее в функцию, которая принимает неконстантный вектор, но который вы просто так не знаете, не будет изменять вектор.

Последнее является одной из тех вещей, которые, совершенно справедливо, заставят любого, кто видит, что он комментирует очки, и тот факт, что они ничего не делают. Это именно то, для чего предназначен const_cast, но есть достаточно сильный аргумент, который говорит, что если вам нужен const_cast, вы уже потеряли.

Выполнение обеих этих вещей (создание вектора const из неконстантного с конструктором копирования, а затем отбрасывание константы), безусловно, неверно – вы должны были просто использовать неконстантный вектор. Поэтому выберите самое большее из них …

[Edit: только что заметил, что вы говорите о различии между вектором и const vector . К сожалению, в STL вектор и vector являются полностью несвязанными типами, и единственный способ конвертировать между ними – это копирование. Это различие между векторами и массивами – T ** может быть бесшумно и безопасно преобразовано в const T * const *]

Короткие и грязные пути (похожие на список Boost’s ())

 #include  #include  #include  #include  using namespace std; template  struct vlist_of : public vector { vlist_of(const T& t) { (*this)(t); } vlist_of& operator()(const T& t) { this->push_back(t); return *this; } }; int main() { const vector v = vlist_of(1)(2)(3)(4)(5); copy(v.begin(), v.end(), ostream_iterator(cout, "\n")); } 

Теперь у C ++ 11 есть списки инициализаторов, поэтому вам не нужно это делать или даже использовать Boost. Но, например, вы можете сделать выше в C ++ 11 более эффективно:

 #include  #include  #include  #include  using namespace std; template  struct vlist_of : public vector { vlist_of(T&& t) { (*this)(move(t)); } vlist_of& operator()(T&& t) { this->push_back(move(t)); return *this; } }; int main() { const vector v = vlist_of(1)(2)(3)(4)(5); for (const auto& i: v) { cout << i << endl; } } 

Но это все еще не так эффективно, как использование списка инициализаторов C ++ 11, потому что для вектора нет оператора = (vlist_of &&).

Изменение пути tjohns20, как и следующее, может быть лучше c ++ 11 vlist_of:

 #include  #include  #include  using namespace std; template  class vlist_of { public: vlist_of(T&& r) { (*this)(move(r)); } vlist_of& operator()(T&& r) { v.push_back(move(r)); return *this; } vector&& operator()() { return move(v); } private: vector v; }; int main() { const auto v = vlist_of(1)(2)(3)(4)(5)(); for (const auto& i : v) { cout << i << endl; } } 

Как говорили другие, вы не можете инициализировать вектор так же, как вы можете инициализировать массив C-style, если только вы не дадите ему указатели на исходный массив. Но в этом случае, если ваш вектор является глобальной константой, почему бы не использовать вместо этого старый массив C-style?

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

Вы можете сделать это в два этапа:

 namespace { const T s_actual_array[] = { ... }; const std::vector 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 v(ar, ar+TotalItems); 

Старый вопрос, но я столкнулся с тем же вопросом сегодня, вот подход, который был наиболее приемлемым для моих целей:

 vector initVector(void) { vector initializer; initializer.push_back(10); initializer.push_back(13); initializer.push_back(3); return intializer; } int main() { const vector a = initVector(); return 0; } 

Пример, чтобы избежать чрезмерного копирования:

 vector & initVector(void) { static vector initializer; if(initializer.empty()) { initializer.push_back(10); initializer.push_back(13); initializer.push_back(3); } return intializer; } int main() { const vector & a = initVector(); return 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]; 

Опасайтесь добавления более чем следующей мощности из 2 элементов, даже если используется push_back (). Указатели на v.begin () будут недействительными.

Если они все равно, вы можете просто сделать

 vector vec(num_items, item); 

но я предполагаю, что это не так – в этом случае, возможно, самый опрятный путь:

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

C ++ 0x позволит вам использовать список инициализаций точно так, как вы думаете, но сейчас это не очень хорошо.

Основываясь на ответе Shadow2531, я использую этот class для инициализации векторов, фактически не наследуя от std :: vector, как решение Shadow

 template  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 end() { return vec; } private: std::vector vec; }; 

Применение:

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

По сравнению с решением Стива Джессопа он создает намного больше кода, но если создание массива не критично для производительности, я считаю его хорошим способом инициализировать массив в одной строке

  • Почему вектор не является контейнером STL?
  • уменьшить емкость stl-вектора
  • Как повторно использовать ostringstream?
  • Список сортировки с использованием функции сортировки STL
  • STL-вектор и безопасность streamов
  • Есть ли стандартный class даты / времени в C ++?
  • Защита streamов std :: map для операций только для чтения
  • Что произойдет, если вы вызываете erase () на элементе карты, итерации от начала до конца?
  • Определите, является ли тип контейнером STL во время компиляции
  • Нельзя наследовать от std :: vector
  • Является ли stl-вектор одновременным чтением streamобезопасным?
  • Давайте будем гением компьютера.