Инициализация std :: vectorсо списком последовательных целых чисел без знака - PullRequest
9 голосов
/ 13 января 2012

Я хочу использовать специальный метод для инициализации std::vector<unsigned int>, который описан в книге на C ++, которую я использую в качестве справочной (немецкая книга 'Der C ++ Programmer' Ульриха Бреймана, на случай, если это имеет значение).В этой книге есть раздел о типах последовательностей STL, относящийся, в частности, к list, vector и deque.В этом разделе он пишет, что есть два специальных конструктора таких типов последовательностей, а именно, если X относится к такому типу,

X(n, t) // creates a sequence with n copies of t
X(i, j) // creates a sequence from the elements of the interval [i, j)

Я хочу использовать второй для интервала unsigned int, то есть

std::vector<unsigned int> l(1U, 10U);

, чтобы получить список, инициализированный {1,2,...,9}.Однако я получаю вектор с одним unsigned int со значением 10: - |Существует ли второй вариант, и если да, как заставить его называться?

Ответы [ 5 ]

20 голосов
/ 15 августа 2013

есть как минимум три способа сделать это.Один из них был упомянут ранее Брайаном

//method 1
generate(v.begin(), v.end(), [] { static int i {1}; return i++; });     

Вы также можете использовать std :: iota, если вы используете c ++ 11

//method 2
iota(v.begin(), v.end(), 1);

Или вместо этого вы можете инициализировать свой контейнер с 1 изатем сделайте частичную сумму на это.Я не думаю, что кто-то будет использовать этот третий метод в любом случае:)

//method 3
vector<int> v(n, 1);                                                     
partial_sum(v.begin(), v.end(), v.begin()); 
10 голосов
/ 13 января 2012

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

std::vector<unsigned int> numbers(
     boost::counting_iterator<unsigned int>(0U),
     boost::counting_iterator<unsigned int>(10U));
3 голосов
/ 13 января 2012

Безошибочный способ сделать это с помощью инкрементного итератора.

#include <vector>
#include <iostream>
#include <algorithm>

static int NUM_ITEMS = 10;

class gen_range {
    public:
        gen_range(int i) { idx = i; }
        int operator()() { return (idx++); };

    int idx;
};

int main() {

    std::vector<int> x(NUM_ITEMS);
    std::generate_n(x.begin(), NUM_ITEMS, gen_range(0));

    for (int i=0; i < x.size(); i++) {
        std::cout << x[i] << std::endl;
    }
}
2 голосов
/ 25 июня 2013

C ++ 11:

std::vector<int> idxs (n);

std::generate_n (idxs.begin (), n, [] { static int i {1}; return i++; });
1 голос
/ 13 января 2012

Нет, этот вариант не существует.Второй конструктор инициализирует вектор из двух итераторов, которые указывают на другую последовательность.

Вот пример конструктора с двумя итераторами в действии:

int fill_data[4] = { 1, 2, 3, 4 };
std::vector<int> v(fill_data, fill_data + 4);
...