2012-01-13 5 views
9

Desidero utilizzare un metodo speciale per inizializzare uno std::vector<unsigned int> che è descritto in un libro C++ che uso come riferimento (il libro tedesco 'Der C++ Programmatore 'di Ulrich Breymann, nel caso ciò che conta). In quel libro c'è una sezione sui tipi di sequenza dell'STL, facendo riferimento in particolare a list, vector e deque. In questa sezione scrive che ci sono due costruttori particolari di tali tipi sequenza, vale a dire, se X si riferisce ad un tale tipo,Inizializzazione di std :: vector <unsigned int> con un elenco di interi consecutivi senza segno

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) 

voglio usare la seconda per un intervallo di unsigned int, cioè

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

per ottenere una lista inizializzata con {1,2,...,9}. Quello che ottengo, tuttavia, è un vettore con uno unsigned int con valore 10: - | Esiste la seconda variante, e se sì, come faccio a forzare che sia chiamato?

risposta

10

rileggere i paragrafi vicino ci descrive cosa ciascuno dei parametri sono. Nello specifico, dovrebbe menzionare che i e j non sono valori, ma iteratori. Questo costruttore è molto comunemente usato per fare copie di altri tipi di contenitori. Se si desidera ottenere una sequenza di valori, Boost library fornisce uno counting iterator, che fa esattamente ciò che si desidera.

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

grazie, funziona come desiderato! Il libro è un po 'non specifico rispetto a quel particolare costruttore, ma in seguito le lettere i, j sono infatti usate esplicitamente per gli iteratori. Th. – Thomas

0

No, questa variante non esiste. Il secondo costruttore inizializza un vettore da due iteratori che puntano in un'altra sequenza.

Ecco un esempio del costruttore "due iteratore" in azione:

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

Grazie per la richiesta di modifica, l'ho erroneamente contrassegnato come errato. :) L'ho risolto. –

2

Un modo non boost per eseguire questa operazione con un iteratore auto-incrementante.

#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; 
    } 
} 
1

C++ 11:

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

std::generate_n (idxs.begin(), n, [] { static int i {1}; return i++; }); 
19

ci sono almeno tre modi che si possono fare che. Uno è stato menzionato in precedenza da Brian

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

È inoltre possibile utilizzare std :: iota se si utilizza C++ 11

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

O invece è possibile inizializzare il vostro contenitore con 1s e poi fare un parziale somma su questo. Non credo che nessuno userà comunque questo terzo metodo :)

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

Il metodo 3 è piuttosto utile se si desidera generare una matrice contenente le somme cumulative. Aggiungi un altro 'partial_sum (v.begin(), v.end(), v.begin())' e per n = 5, ottieni {1, 3, 6, 10, 15}. – lifebalance

+0

Nota, 'generate' qui usa static. Mettilo in una funzione, chiamalo più volte e continuerà a contare. Usa 'ValueType i = {1}; std :: generate (first, last, [& i] {return i ++;}); 'invece. –