简体   繁体   中英

Initialization of std::vector<unsigned int> with a list of consecutive unsigned integers

I want to use a special method to initialize a std::vector<unsigned int> which is described in a C++ book I use as a reference (the German book 'Der C++ Programmer' by Ulrich Breymann, in case that matters). In that book is a section on sequence types of the STL, referring in particular to list , vector and deque . In this section he writes that there are two special constructors of such sequence types, namely, if X refers to such a type,

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)

I want to use the second one for an interval of unsigned int , that is

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

to get a list initialized with {1,2,...,9} . What I get, however, is a vector with one unsigned int with value 10 :-| Does the second variant exist, and if yes, how do I force that it is called?

there are at least three ways that you can do that. One was mentioned earlier by Brian

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

You can also use std::iota if you are using c++11

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

Or instead you can initialize your container with 1s and then do a partial sum on that. I don't think anybody will use this third method anyway :)

//method 3
vector<int> v(n, 1);                                                     
partial_sum(v.begin(), v.end(), v.begin()); 

Reread the paragraphs near there describing what each of the parameters are. Specifically, it should mention that i and j are not values, but iterators . This constructor is very commonly used to make copies of other types of containers. If you want to get a sequence of values, the Boost library provides a counting iterator , that does exactly what you want.

std::vector<unsigned int> numbers(
     boost::counting_iterator<unsigned int>(0U),
     boost::counting_iterator<unsigned int>(10U));

A non-boost way to do this with a self-incrementing iterator.

#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++; });

No, that variant does not exist. The second constructor initializes a vector from two iterators that point into another sequence.

Here is an example of the "two-iterator" constructor in action:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM