Я попытался напечатать количество байтов и адрес памяти элементов, которые находятся в векторе. В результате я вижу адрес памяти и номер байта. Элементы вектора хранятся отдельно? и если да, то почему мой код выдает, что вектор всего 24 байта?
#include <iostream>
#include <vector>
int main(){
std::vector<const char *> colour = {"Microsoft", "Apple", "DELL", "Accer", "Lenovo", "hp"};
std::cout << "VectorSize : " << sizeof(colour) << "\n" << std::endl;
for(int i = 0; i < colour.size(); i++){
std::cout << colour[i] << " is " << sizeof(colour[i]) << " byte at " << &colour[i] << "." << std::endl;
}
}
VectorSize : 24
Microsoft is 8 byte at 0x27b5a7c6220.
Apple is 8 byte at 0x27b5a7c6228.
DELL is 8 byte at 0x27b5a7c6230.
Accer is 8 byte at 0x27b5a7c6238.
Lenovo is 8 byte at 0x27b5a7c6240.
«Элементы вектора хранятся отдельно?» Да. "...и если да, то почему мой код выдает мне, что вектор всего 24 байта?" Потому что элементы хранятся отдельно.
По теме: sizeof Vector равен 24?





Данные в векторе выделяются динамически и хранятся в другой ячейке памяти, они не являются частью вектора, и вектор имеет только указатель на эту память. Выделенная память является непрерывной, поэтому все выделенные байты располагаются рядом друг с другом в памяти.
В вашем случае размер класса std::vector составляет 24 байта, размер дополнительной выделенной памяти где-то еще в памяти составляет 40 байт. Таким образом, всего в памяти вашего компьютера будет выделено 64 байта.
Но расходует ли мой вектор 24 байта или 40 байт?
С тем, что ты сказал.
Хорошо, спасибо за ваш ответ. Но я думаю, что это важный момент, который вы только что сказали (64 байта в памяти). Я рекомендую вам поставить его на ваш ответ.
Без проблем!
sizeof(...) измеряет размер объекта. Это не связано с количеством элементов, которые имеет std::vector. Напишите colour.size(), чтобы вычислить это. С вектором sizeof(std::vector) == 24 потому, что он содержит указатель на данные, текущее количество элементов и емкость выделенных данных, каждый из которых занимает 8 байтов в вашей архитектуре. В разных реализациях это может быть реализовано по-разному.
Да, как вы можете видеть, расположение указателя каждый раз увеличивается на 8, так как данные вектора хранятся непрерывно.
Векторы используют память в двух местах: 1. внутри самого векторного объекта и 2. в куче, где хранятся векторные элементы.
Разработчики компилятора имеют большую свободу в том, как они распределяют эту память. Однако обычно сам векторный объект содержит части, размер которых не меняется. Вот что я нашел в реализации Microsoft:
Указатель на начало данных в куче, т. е. на первый элемент данных.
Указатель на конец данных, т. е. один элемент после последнего элемента данных. Используя этот указатель, capacity() вычисляется как end - first.
Указатель, обозначающий последний использованный элемент, т. е. указатель на элемент, следующий за последним использованным элементом данных. С этим указателем size() вычисляется как last - first.
Элементы данных хранятся в куче, потенциально с другой информацией, специфичной для реализации (или без нее).
Для данного вектора v, предполагая, что в куче ничего, кроме данных, не хранится, количество используемых байтов будет:
sizeof(v) + (v.data() == nullptr ? 0 : v.capacity() * sizeof(*v.data()))
Вектор в исходном вопросе представляет собой вектор указателей, в частности указателей на const char. Вектор инициализируется initializer_list с 6 string literals. Строковые литералы хранятся в статической памяти, а указатели на них — в куче. Предположительно, емкость была выделена на уровне 6, но я считаю, что эта деталь зависит от реализации. Размер каждого элемента равен размеру указателя данных, обычно это sizeof(std::size_t).
Вот короткая программа для подсчета общего количества используемых байтов.
#include <cstddef>
#include <iostream>
#include <vector>
int main()
{
std::vector<const char*> v = { "Microsoft", "Apple", "DELL", "Accer", "Lenovo", "hp" };
std::cout << std::boolalpha
<< "sizeof(v) : " << sizeof(v)
<< "\nv.size() : " << v.size()
<< "\nv.capactity() : " << v.capacity()
<< "\nv.data() == nullptr : " << (v.data() == nullptr)
<< "\nv.data() : " << v.data()
<< "\nsizeof(*v.data()) : " << sizeof(*v.data())
<< "\nsizeof(std::size_t) : " << sizeof(std::size_t)
<< "\nTotal bytes used : " << sizeof(v) + (v.data() == nullptr ? 0 : v.capacity() * sizeof(*v.data()))
<< "\n\n"
;
return 0;
}
Я запускал MSVC с таргетингом на x64, поэтому мои указатели были по 8 байт каждый. Очевидно, в векторном объекте хранится четвертый элемент, потому что sizeof(v) получилось 32, а не 24.
Прочитав исходный код Microsoft для заголовка <vector>, я смог найти три указателя, упомянутых выше. Они хранятся в объекте с именем _Mypair как _Mypair._Myval2. Однако я не смог найти определение для _Mypair._Myval1, которое, предположительно, является четвертым элементом.
sizeof(v) : 32
v.size() : 6
v.capactity() : 6
v.data() == nullptr : false
v.data() : 000002952A005030
sizeof(*v.data()) : 8
sizeof(std::size_t) : 8
Total bytes used : 80
Когда я перекомпилировал, ориентируясь на x86, размер был уменьшен вдвое. Это имеет смысл, потому что размер std::size_t, используемый для указателей, был сокращен до 4 байтов.
sizeof(v) : 16
v.size() : 6
v.capactity() : 6
v.data() == nullptr : false
v.data() : 00AEC640
sizeof(*v.data()) : 4
sizeof(std::size_t) : 4
Total bytes used : 40
Дополнительное примечание рассмотрите возможность использования
std::vector<std::string_view>(чтобы избежать использования необработанных указателейconst char*в вашем коде.