Инициализация вектора std::со списком последовательных целых чисел без знака
Я хочу использовать специальный метод для инициализации 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 ответов:
Перечитайте абзацы рядом с описанием того, что такое каждый из параметров. В частности, следует отметить, что
iиjне являются значениями, А итераторами. Этот конструктор очень часто используется для создания копий других типов контейнеров. Если вы хотите получить последовательность значений, Библиотека Boost предоставляет итератор подсчета, который делает именно то, что вы хотите.std::vector<unsigned int> numbers( boost::counting_iterator<unsigned int>(0U), boost::counting_iterator<unsigned int>(10U));
Есть, по крайней мере, три способа, которыми вы можете это сделать. Один из них был упомянут ранее Брайаном
//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);Или вместо этого вы можете инициализировать свой контейнер с помощью 1s, а затем сделать частичную сумму на этом. Я не думаю, что кто-то будет использовать этот третий метод в любом случае :)
//method 3 vector<int> v(n, 1); partial_sum(v.begin(), v.end(), v.begin());
Не-повышающий способ сделать это с помощью самоинкрементирующегося итератора.
#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; } }
C++11:
std::vector<int> idxs (n); std::generate_n (idxs.begin (), n, [] { static int i {1}; return i++; });
Нет, такого варианта не существует. Второй конструктор инициализирует вектор из двух итераторов, которые указывают на другую последовательность.
Вот пример конструктора "два итератора"в действии:
int fill_data[4] = { 1, 2, 3, 4 }; std::vector<int> v(fill_data, fill_data + 4);
Comments