7

Как проще всего инициализировать std::vector с жестко заданными элементами?

4

Я могу создать массив и инициализировать его следующим образом:

int a[] = {10, 20, 30};

Как мне создать std::vector и инициализировать его таким же элегантным способом?

Лучший способ, который я знаю, это:

std::vector<int> ints;

ints.push_back(10);
ints.push_back(20);
ints.push_back(30);

Есть ли какой-то лучший способ?

5 ответ(ов)

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]) вычисляет количество элементов в массиве, что позволяет правильно задать границы вектора.

1

Если возможно, используйте современный C++ (версии 11, 14, 17, 20 и т.д.):

std::vector<int> ints = {10, 20, 30};

Старый способ перебора массивов переменной длины или использование sizeof() выглядит действительно ужасно и совершенно ненужен с точки зрения интеллектуальных затрат. Фу.

0

В стандарте 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))

Эти методы помогут вам безопасно и эффективно управлять размерами массивов в вашем коде.

0

В C++11 вы можете инициализировать вектор несколькими способами, которые рассмотрены ниже:

  1. Инициализация через список инициализации:

    #include <vector>
    using std::vector;
    ...
    vector<int> vec1 { 10, 20, 30 };
    // или
    vector<int> vec2 = { 10, 20, 30 };
    
  2. Использование list_of из библиотеки Boost:

    #include <vector>
    #include <boost/assign/list_of.hpp>
    using std::vector;
    ...
    vector<int> vec = boost::assign::list_of(10)(20)(30);
    
  3. Использование Boost assign для добавления элементов:

    #include <vector>
    #include <boost/assign/std/vector.hpp>
    using std::vector;
    ...
    vector<int> vec;
    vec += 10, 20, 30;
    
  4. Обычный способ с использованием STL:

    #include <vector>
    using std::vector;
    ...
    static const int arr[] = {10, 20, 30};
    vector<int> vec(arr, arr + sizeof(arr) / sizeof(arr[0]));
    
  5. Конвенциональный 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));
    
  6. Конвенциональный 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);
    

Каждый из подходов имеет свои особенности и преимущества, и выбор того или иного способа может зависеть от конкретной ситуации или предпочтений программиста.

0

Вы можете удобно создать функцию для преобразования обычного массива в 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);

Таким образом, вам не придется вручную заполнять вектор значениями из массива — всё будет сделано автоматически. Этот подход делает код чище и более читаемым.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь