2012-03-13 1 views
29

utilizzando il seguente codice:cosa significa l'errore quando sto compilando C++ con il compilatore g ++?

#include<iostream> 
#include<vector> 

using namespace std; 

int main() 
{ 
    vector<int> ivec; 
    for(vector<int>::size_type ix = 0; ix != 10; ix++) 
    { 
     ivec.push_back(ix); 
    } 
    vector<int>::iterator mid = (ivec.begin() + ivec.end())/2; 
    cout << *mid << endl; 
    return 0; 
} 

ottengo un errore compilazione con g ++:

iterator_io.cpp: In function `int main()': 
iterator_io.cpp:13: error: no match for 'operator+' in '(&ivec)->std::vector<_Tp,    _Alloc>::begin [with _Tp = int, _Alloc = std::allocator<int>]() + (&ivec)->std::vector<_Tp, _Alloc>::end [with _Tp = int, _Alloc = std::allocator<int>]()' 
/usr/lib/gcc/x86_64-redhat-linux/3.4.5/../../../../include/c++/3.4.5/bits/stl_iterator.h:654: note: candidates are: __gnu_cxx::__normal_iterator<_Iterator, _Container> __gnu_cxx::__normal_iterator<_Iterator, _Container>::operator+(const typename std::iterator_traits<_Iterator>::difference_type&) const [with _Iterator = int*, _Container = std::vector<int, std::allocator<int> >] 
/usr/lib/gcc/x86_64-redhat-linux/3.4.5/../../../../include/c++/3.4.5/bits/stl_bvector.h:261: note:     std::_Bit_iterator std::operator+(ptrdiff_t, const std::_Bit_iterator&) 
/usr/lib/gcc/x86_64-redhat-linux/3.4.5/../../../../include/c++/3.4.5/bits/stl_bvector.h:345: note:     std::_Bit_const_iterator std::operator+(ptrdiff_t, const std::_Bit_const_iterator&) 
/usr/lib/gcc/x86_64-redhat-linux/3.4.5/../../../../include/c++/3.4.5/bits/stl_iterator.h:765: note:     __gnu_cxx::__normal_iterator<_Iterator, _Container> __gnu_cxx::operator+(typename __gnu_cxx::__normal_iterator<_Iterator, _Container>::difference_type, const __gnu_cxx::__normal_iterator<_Iterator, _Container>&) [with _Iterator = int*, _Container = std::vector<int, std::allocator<int> >] 

So che l'ivec.end() non può essere utilizzato come un normale elemento del vettore. Ma non riesco a capire cosa significhi l'informazione di errore ... qualcosa su operator +?

+9

+1 per una prima domanda ben formulata e correttamente codificata. – razlebe

+8

+1 per includere un breve programma di esempio completo. http://sscce.org/ –

risposta

23

Si non è possibile aggiungere due iteratori insieme.

operator+ non è definito per due iteratori, poiché tale operazione non avrebbe senso. Gli iteratori sono una sorta di generalizzazione sui puntatori: indicano l'elemento specifico memorizzato nel contenitore. A quale elemento sta puntando la somma degli iteratori?

Tuttavia, quando si utilizza un vettore, è possibile aggiungere interi a iteratori, come quella:

vec.begin() + vec.size()/2 

, per questo avete candidates are: (...) nel messaggio di errore, seguito da alcune definizioni di operator+.

Nel tuo caso il modo migliore, più pulito e non sarà utilizzando le iteratori, ma semplice ottenere il valore dalla posizione specificata:

int mid = vec[vec.size()/2]; 
+3

Utilizzare' at' qui non è ortodosso, per non dire altro. Nel caso attuale, non ci può * mai * essere un errore di accesso, quindi perché guardarsi da questo? –

+0

Sono d'accordo, 'a()' cambiato in '[]'. –

2

Non è possibile aggiungere due iteratori insieme, perché gli iteratori non sono interi. Questo è ciò che significa il messaggio di errore. Se si desidera accedere all'elemento nel mezzo di un vettore, utilizzare ivec[ivec.size()/2].

7

Significa semplicemente che gli iteratori vector non hanno operatore di addizione (+). Non è possibile aggiungere ivec.begin() e ivec.end().

Per ottenere l'elemento centrale, si può semplicemente utilizzare l'operatore pedice:

cout << ivec[ivec.size()/2] << endl; 

Se ti ostini a usare un iteratore, si può ottenere un iteratore che punta al centro in questo modo:

vector<int>::iterator mid = ivec.begin(); 
mid += ivec.size()/2; 
cout << *mid << endl; 

È possibile eseguire questa operazione perché l'iteratore vector è un iteratore di accesso casuale (in tutte le implementazioni di cui sono a conoscenza incapsula un puntatore effettivo sui dati del contenitore non elaborati).

+0

In molti build di debug come MSVC, 'vector :: iterator' mantiene anche i limiti dell'array. Ciò significa che prenderà la maggior parte degli errori fuori dai limiti nel debugging. – MSalters

+0

@MSalters: Sì, ma il mio punto era, che tiene anche il puntatore alla sequenza non elaborata (array). – bitmask

22

Non è possibile aggiungere iteratori. Cosa si può fare:

vector<int>::iterator mid = ivec.begin() + distance(ivec.begin(), ivec.end())/2; 
+4

+1 per l'utilizzo di std :: distance() – ComicSansMS

+0

'' distance (vector :: begin, vector :: end) 'non è uguale a' vector :: size'? –

+3

@PeterWood - In questo caso, sì. Ma la distanza funziona anche per altri contenitori, non solo per il vettore. – Henrik

3

non è possibile aggiungere due iteratori

uso presso per ottenere l'elemento centrale:

ivec.at (ivec.size()/2);

+0

@ Henrik: mancanza di contesto. Questo sarà: 'cout << ivec.at (ivec.size()/2) << endl;'. Se sai che 'ivec' non è vuoto, puoi anche scrivere' cout << ivec [ivec.size()/2] << endl; ' – MSalters

6

Non è possibile aggiungere iteratori.

Che cosa si vorrà utilizzare è una combinazione di std::distance() e std::advance():

vector<int>::iterator mid = std::advance(ivec.begin(), std::distance(ivec.begin(), ivec.end())/2); 

Perché utilizzare std::advance() invece di operatore di addizione del iteratore? std::advance() funziona in modo ottimale indipendentemente dal tipo di iteratore (accesso casuale, solo inoltro, bidirezionale, ecc.), Pertanto se si passa da std::vector a std::list, il codice sopra riportato può rimanere invariato e continuare a funzionare in modo ottimale.

+0

Questo non è ottimale per 'std :: list' più. In C++ 11, 'std :: distance (ilist.begin(), ilist.end())' può ancora essere O (N) ma 'ilist.size()' restituisce lo stesso valore in O (1). – MSalters

+0

@MSalters: interessante! Perché il cambiamento? – luke

+0

C++ 03 consentito entrambi, con un compromesso necessario su 'splice'. Di conseguenza, il codice portatile doveva trattare sia 'size' che' splice' come O (N). C++ 11 ha reso 'size' portably O (1). – MSalters