Как проще всего инициализировать std::vector с жестко заданными элементами?
Я могу создать массив и инициализировать его следующим образом:
int a[] = {10, 20, 30};
Как мне создать std::vector
и инициализировать его таким же элегантным способом?
Лучший способ, который я знаю, это:
std::vector<int> ints;
ints.push_back(10);
ints.push_back(20);
ints.push_back(30);
Есть ли какой-то лучший способ?
5 ответ(ов)
Один из способов инициализировать вектор — использовать массив. Вот пример кода:
static const int arr[] = {16, 2, 77, 29};
vector<int> vec(arr, arr + sizeof(arr) / sizeof(arr[0]));
В данном примере мы создаем статический массив arr
и затем инициализируем вектор vec
, передавая ему итераторы, указывающие на начало и конец массива. sizeof(arr) / sizeof(arr[0])
вычисляет количество элементов в массиве, что позволяет правильно задать границы вектора.
Если возможно, используйте современный C++ (версии 11, 14, 17, 20 и т.д.):
std::vector<int> ints = {10, 20, 30};
Старый способ перебора массивов переменной длины или использование sizeof()
выглядит действительно ужасно и совершенно ненужен с точки зрения интеллектуальных затрат. Фу.
В стандарте C0x (современный C) можно будет делать это так же, как с обычным массивом, однако в текущем стандарте это невозможно.
Если придерживаться только стандартной библиотеки, можно использовать следующий код:
int tmp[] = { 10, 20, 30 };
std::vector<int> v(tmp, tmp + 3); // используйте некоторую утилиту, чтобы избежать жесткого кодирования размера массива
Если вы можете подключить другие библиотеки, вы можете попробовать использовать boost::assignment
:
std::vector<int> v = boost::assign::list_of(10)(20)(30);
Чтобы избежать жесткого кодирования размера массива, есть несколько способов:
// вариант 1, типобезопасный, не является константой времени компиляции
template <typename T, std::size_t N>
inline std::size_t size_of_array(T (&)[N]) {
return N;
}
// вариант 2, не типобезопасный, является константой времени компиляции
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
// вариант 3, типобезопасный, является константой времени компиляции
template <typename T, std::size_t N>
char (&sizeof_array(T(&)[N]))[N]; // объявлен, не определен
#define ARRAY_SIZE(x) sizeof(sizeof_array(x))
Эти методы помогут вам безопасно и эффективно управлять размерами массивов в вашем коде.
В C++11 вы можете инициализировать вектор несколькими способами, которые рассмотрены ниже:
Инициализация через список инициализации:
#include <vector> using std::vector; ... vector<int> vec1 { 10, 20, 30 }; // или vector<int> vec2 = { 10, 20, 30 };
Использование
list_of
из библиотеки Boost:#include <vector> #include <boost/assign/list_of.hpp> using std::vector; ... vector<int> vec = boost::assign::list_of(10)(20)(30);
Использование Boost
assign
для добавления элементов:#include <vector> #include <boost/assign/std/vector.hpp> using std::vector; ... vector<int> vec; vec += 10, 20, 30;
Обычный способ с использованием STL:
#include <vector> using std::vector; ... static const int arr[] = {10, 20, 30}; vector<int> vec(arr, arr + sizeof(arr) / sizeof(arr[0]));
Конвенциональный STL с использованием макросов:
#include <vector> #define ARRAY_SIZE(ar) (sizeof(ar) / sizeof(ar[0])) #define ARRAY_END(ar) (ar + ARRAY_SIZE(ar)) using std::vector; ... static const int arr[] = {10, 20, 30}; vector<int> vec(arr, ARRAY_END(arr));
Конвенциональный STL с макросом для инициализации вектора:
#include <vector> #define INIT_FROM_ARRAY(ar) (ar, ar + sizeof(ar) / sizeof(ar[0])) using std::vector; ... static const int arr[] = {10, 20, 30}; vector<int> vec INIT_FROM_ARRAY(arr);
Каждый из подходов имеет свои особенности и преимущества, и выбор того или иного способа может зависеть от конкретной ситуации или предпочтений программиста.
Вы можете удобно создать функцию для преобразования обычного массива в std::vector
, используя следующий шаблон:
template<typename T, size_t N>
std::vector<T> makeVector(const T (&data)[N])
{
return std::vector<T>(data, data + N);
}
Обычно я объявляю эту функцию в заголовочном файле утилит, и тогда её использование становится очень простым. Например, если у вас есть массив значений:
const double values[] = { 2.0, 1.0, 42.0, -7 };
Вы можете легко создать вектор из этого массива, вызвав makeVector
:
std::vector<double> array = makeVector(values);
Таким образом, вам не придется вручную заполнять вектор значениями из массива — всё будет сделано автоматически. Этот подход делает код чище и более читаемым.
Как узнать, присутствует ли элемент в std::vector?
Имеют ли круглые скобки после имени типа значение при использовании new?
Как удалить элемент из std::vector<> по индексу?
Как проверить, существует ли заданный ключ в std::map?
Каковы преимущества инициализации списка (с использованием фигурных скобок)?