Ответ 1
Для каждого примитивного типа данных ячейки памяти являются смежными, кроме
char
. Он выводит некоторые значения мусора на экран.
"Области памяти" являются смежными одинаково для обоих случаев. Разница лишь в том, как вы отображаете свои результаты. Когда вы делаете:
cout << "Data: " << vChar[i] << " Address:" << &vChar[i] << "\n";
вы даете std::operator<<(std::basic_ostream)
char*
, так как вы применяете &
(address-of) к одному char
1 из vector
, что заставляет его рассматривать его как стиль C строка - то есть ищет завершающий ноль В вашем случае этот нуль действительно после некоторого мусора действительно. 2 Но у вас обязательно будет какой-то мусор после vector<int>
, только вы его не печатаете. 3
Если вы хотите получить ту же распечатку, что и для vector<int>
, то вы можете явно привести к void
указателю, поэтому std::cout
будет рассматривать его как адрес для печати (здесь перегрузка (7)), а не строка:
cout << "Data: " << vChar[i] << " Address:" << static_cast<void*>(&vChar[i]) << "\n";
В этом случае вывод:
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
1char&
если быть точным, так как std::vector<T>::operator[]
возвращает T&
.
2 Обратите внимание, что поиск этого завершающего нуля, который не был помещен вами, представляет собой неопределенное поведение, так как он потенциально дает вам доступ к памяти, к которой этот доступ не предназначен.
3 Вы можете сами убедиться в этом, если выполните обратное приведение, чтобы std::cout
рассматривал vector<int>
элементы vector<int>
как строки в стиле C:
cout << "Data: " << vInt[i] << " Address:" << reinterpret_cast<char*>(&vInt[i]) << "\n";
Опять же, просто запомните, что это означает неопределенное поведение, так как код печати будет искать в памяти завершающий ноль, в то время как у вас точно не было его для его поиска.