Innanzitutto, notare che in questo caso non è necessario utilizzare lo standard std::copy
. Si può solo inizializzare il vettore direttamente dalle iteratori:
vector<string> col((istream_iterator<string>(cin)),
istream_iterator<string>());
Questo probabilmente non rende il codice molto più semplice da capire però.
Per quanto riguarda il funzionamento del codice, è probabilmente un po 'più veloce di quanto si pensi.Un istream_iterator sembra vagamente simile a questo:
template <class T>
class istream_iterator {
std::istream *is;
T data;
public:
istream_iterator(std::istream &is) : is(&is) { ++(*this); }
istream_iterator() : is(nullptr) {}
T operator++() { (*is) >> data; return *this; }
T operator++(int) { (*is) >> data; return *this; }
T const &operator*() { return data; }
bool operator !=(istream_iterator &end) { return (*is).good(); }
bool operator ==(istream_iterator &end) { return !(*is).good(); }
};
Ovviamente c'è di più più mi sto saltando, ma che è più di quello che ci sta a cuore qui. Quindi, quello che succede è che quando crei l'iteratore, legge (o tenta di) un elemento dallo stream nella variabile che ho chiamato data
. Quando si dereferenzia l'iteratore, restituisce data
. Quando si incrementa l'iteratore, legge (o tenta di) l'elemento successivo dal file. Nonostante siano scritti come se confrontassero un iteratore con un altro, operator==
e operator!=
in realtà basta controllare la fine del file .
che è poi utilizzato per std::copy
, che (ancora una volta semplificato) sembra vagamente simile a questo:
template <class InIt, class OutIt>
void std::copy(InIt b, InIt e, OutIt d) {
while (b != e) {
*d = *b;
++b;
++d;
}
}
Quindi, questa legge e voce dal iteratore di input, scrive che voce per l'iteratore di uscita, e si ripete fino a quando il l'iteratore per la posizione corrente è paragonabile all'iteratore per la fine dell'input (che avverrà quando si raggiunge la fine del file). Nota che a differenza di altri iteratori, l'unica posizione di "fine" che puoi utilizzare con un iteratore di istream è la fine del file.
- noti che tecnicamente, questo non è conforme comportamento. Ho semplificato il confronto per mantenere le cose semplici. Due iteratori costruiti in modo predefinito devono essere paragonati e, se si costruiscono due iteratori dallo stesso flusso, è necessario confrontarli almeno prima di aver letto qualcosa dallo stream. Ciò tuttavia fa una piccola differenza pratica: l'unico paragone che si è visto nell'uso reale è determinare se si è giunti alla fine del file.
è meglio leggere il libro "The C++ STL" –