Considérer:
#include <vector>
#include <string>
#include <iostream>
using namespace std;
int main()
{
vector<char> vChar;
vChar.Push_back('a');
vChar.Push_back('b');
vChar.Push_back('c');
vChar.Push_back('d');
vector<int> vInt;
vInt.Push_back(1);
vInt.Push_back(2);
vInt.Push_back(3);
vInt.Push_back(4);
cout << "For char vector Size:" << vChar.size() << " Capacity:" << vChar.capacity() << "\n";
for(int i=0; i < vChar.size(); i++)
{
cout << "Data: " << vChar[i] << " Address:" << &vChar[i] << "\n";
}
cout << "\nFor int vector Size:" << vInt.size() << " Capacity:" << vInt.capacity() << "\n";
for (int i = 0; i < vInt.size(); i++)
{
cout << "Data: " << vInt[i] << " Address:" << &vInt[i] << "\n";
}
return 0;
}
Exemple de sortie pour le code ci-dessus:
For char vector Size:4 Capacity:4
Data: a Address:abcd²²²²αPⁿ▀┬
Data: b Address:bcd²²²²αPⁿ▀┬
Data: c Address:cd²²²²αPⁿ▀┬
Data: d Address:d²²²²αPⁿ▀┬
For int vector Size:4 Capacity:4
Data: 1 Address:000001F020F80420
Data: 2 Address:000001F020F80424
Data: 3 Address:000001F020F80428
Data: 4 Address:000001F020F8042C
Pour chaque type de données primitif, les emplacements de mémoire sont contigus, sauf pour char. Il imprime une valeur de déchets à l'écran.
J'ai essayé d'ajouter v.reserve (4), mais la sortie était la même.
Pour chaque type de données primitif, les emplacements de mémoire sont contigus, à l'exception de
char
. Il imprime une valeur de déchets à l'écran.
Les "emplacements de mémoire" sont contigus de la même manière exacte pour les deux cas. La seule différence réside dans la façon dont vous affichez vos résultats. Quand vous faites:
cout << "Data: " << vChar[i] << " Address:" << &vChar[i] << "\n";
vous donnez std::operator<<(std::basic_ostream)
a char*
, lorsque vous appliquez &
( adresse-de ) sur un seul char
1 à partir de vector
, ce qui le fait traiter comme une chaîne de style C - ce qui signifie qu'il recherche un se terminant par null . Dans votre cas, ce null est juste après quelques ordures.2 Mais vous êtes obligé d'avoir des ordures après le vector<int>
Tout aussi bien, seulement vous ne l'imprimez pas.3
Si vous souhaitez obtenir la même impression que celle que vous obtenez pour le vector<int>
, Vous pouvez explicitement caster vers un pointeur void
, donc std::cout
Le traitera comme une adresse à imprimer ( surcharge (7) ici ), pas une chaîne:
cout << "Data: " << vChar[i] << " Address:" << static_cast<void*>(&vChar[i]) << "\n";
Dans ce cas, la sortie est:
For char vector Size:4 Capacity:4
Data: a Address:0x1c39810
Data: b Address:0x1c39811
Data: c Address:0x1c39812
Data: d Address:0x1c39813
For int vector Size:4 Capacity:4
Data: 1 Address:0x1c39960
Data: 2 Address:0x1c39964
Data: 3 Address:0x1c39968
Data: 4 Address:0x1c3996c
1 char&
Pour être précis, car std::vector<T>::operator[]
Renvoie un T&
.
2 Notez que la recherche de cette terminaison null qui n'a pas été placée par vous constitue un comportement indéfini , car cela vous fait potentiellement accéder à une mémoire qui n'est pas destinée à être utilisée à cette fin.
3 Vous pouvez essayer de le voir par vous-même si vous effectuez la conversion inverse pour que std::cout
Traite les éléments vector<int>
Comme des chaînes de style C:
cout << "Data: " << vInt[i] << " Address:" << reinterpret_cast<char*>(&vInt[i]) << "\n";
Encore une fois, rappelez-vous simplement que cela signifie un comportement indéfini car le code d'impression recherchera en mémoire le zéro de fin alors que vous ne l'avez certainement pas là pour le faire trouver.
std::vector<T>::operator[]()
renvoie T&
, dont l'adresse en cas de char
sera formatée par la surcharge (2) de operator<<(std::basic_ostream)
comme s'il s'agissait d'une chaîne de style C terminée par null (c'est-à-dire une chaîne qui commence à &vChar[i]
et s'arrête au premier \0
trouvé).
Pour le faire fonctionner, utilisez std::cout << static_cast<const void*>(&vChar[i])
pour récupérer la surcharge (7) de std::basic_ostream::operator<<()
.