2010-02-04 7 views
10

J'ai lu ici et d'autres endroits que quand un itérer std :: vecteur en utilisant des index, vous devez:Itérer multiples std :: vecteur

std::vector <int> x(20,1); 
for (std::vector<int>::size_type i = 0; i < x.size(); i++){ 
    x[i]+=3; 
} 

Mais si vous itérez deux vecteurs de différents types:

std::vector <int> x(20,1); 
std::vector <double> y(20,1.0); 
for (std::vector<int>::size_type i = 0; i < x.size(); i++){ 
    x[i]+=3; 
    y[i]+=3.0; 
} 

est-il raisonnable de supposer que

std::vector<int>::size_type

est o f du même type que

std::vector<double>::size_type 

?

Serait-il prudent d'utiliser std :: size_t?

Merci.

+0

Si vous avez appris sur itérer comme ceci, vous avez appris mal. Mis à part le 'i ++' que tout compilateur décent devrait optimiser à un '++ i', vous appelez toujours' x.size() 'à chaque tour de la boucle, ce qui est inutile si ce n'est pas trivial et non inline. –

+0

@Matthieu, juste un exemple rapide et sale pour illustrer ma question. Je devrais aussi utiliser des itérateurs et ne pas le faire par index. – Mark

Répondre

7

Oui, pour presque n'importe quel usage pratique, vous pouvez simplement utiliser std :: size_t. Bien qu'il y ait (en quelque sorte) une intention que différents conteneurs puissent utiliser des types différents pour leurs tailles, il est toujours fondamentalement garanti que (au moins pour les conteneurs standards) size_type est identique à size_t.

Sinon, vous pouvez envisager d'utiliser un algorithme, quelque chose comme:

std::transform(x.begin(), x.end(), x.begin(), std::bind2nd(std::plus<int>(), 3)); 
std::transform(y.begin(), y.end(), y.begin(), std::bind2nd(std::plus<double>(), 3.0)); 
2

En général, le standard C++ ne donne pas de telles garanties: ni l'égalité de size_types pour des conteneurs différemment paramétrés, ni l'égalité avec size_t.

+0

+1. Et vous aviez raison, la garantie 'std :: size_t' est réservée aux allocateurs. Je pensais que 'std :: vector :: size_type' devait être égal à' Allocator :: size_type', mais apparemment pas. – avakar

+0

@avakar: La situation est que l'allocateur standard utilise size_t pour son type_taille, et que toutes les implémentations connues des conteneurs standard transmettent le type_taille à partir de leur allocateur associé. Par conséquent, à moins que vous n'écriviez votre propre allocateur, ce sera size_t. D'un point de vue pratique, size_t va essentiellement toujours fonctionner, indépendamment de ce qu'ils utilisent comme taille_type - par exemple. ':: operator new' utilise size_t pour la taille de l'allocation, et essentiellement toutes les autres allocations passent par là (au moins par défaut). –

1

Eh bien, je pense que:

for (std::vector<int>::size_type i = 0; i < x.size(); i++){ 

est quelque chose d'un conseil de perfection - attendez-vous à vos vecteurs être vraiment gigantesque? Personnellement, j'utilise unsigned int, avec zéro problème.

Et maintenant, je suppose que les downvotes vont commencer ...

+0

@Neil, aime le "conseil de la perfection". J'utilisais un int non signé mais en lisant des trucs comme ça: http://stackoverflow.com/questions/409348/iteration-over-vector-in-c, ça nous inquiète. Inquiétude probablement inutile. – Mark

+0

@Neil: vous ne vivrez jamais si longtemps - personne ne veut être blâmé perfectionniste je suppose :-D –

+2

@Mark Si vous utilisez un type non signé, vous êtes OK, à mon humble avis. La réponse de litb à la question que vous avez liée est (bien sûr) correcte, mais vous devez vraiment aimer taper (dans les deux sens) pour utiliser size_type. –

2

Je pense que vous pouvez supposer que size_type est un entier non signé nonegative. Vous ne pouvez pas compter sur beaucoup plus que cela. Bien sûr, la plupart des conteneurs ont un size_type qui est le même que size_t mais il n'y a aucune garantie.

La documentation SGI et cette source http://www.cplusplus.com/reference/stl/vector/ semblent être d'accord sur ce point.

Vous pouvez également jeter un oeil à cette solution pour votre problème: http://rosettacode.org/wiki/Loop_over_multiple_arrays_simultaneously#C.2B.2B

J'espère que cela aide.

+0

@batbrat, joli lien vers rosettacode, très utile. – Mark

+0

Glad it helps! – batbrat

-1

Vous devez utiliser itérateurs à la place

std::vector <int> x(20,1); 
std::vector <double> y(20,1.0); 
std::vector<double>::iterator j = y.begin(); 
for (std::vector<int>::iterator i = x.begin(); i != x.end(); ++i){ 
    *i +=3; 
    *j +=3.0; 
    ++j; 
} 

Parce qu'il n'y a aucune garantie que u size_type serait le même type interne, de toute façon, pour std::vector vous pouvez itérer en utilisant unsigned int

+1

Pourquoi ne pas incrémenter 'j' dans le corps de contrôle? Et vous aussi souffrez de ne pas utiliser une variable 'max' ou' end' pour vérifier la fin de l'itération ... coller avec 'for_each' vraiment;) –

+0

@MatthieuM, comment pourriez-vous utiliser foreach lorsque vous avez besoin d'itérer sur deux différents vecteurs? Évidemment cet exemple est banal et les boucles peuvent être séparées, je ne peux pas penser à un moyen de le faire pour x [i] = y [i] + 3 –

Questions connexes