Первый случай:
#include <vector>
int main() {
const int iterations = 1'000'000;
std::vector<const char *> c;
for (int i = 0; i < iterations; i++) {
c.push_back("qwertyuiopqwertyuiopqwertyuiopqwertyuiopqwertyuiop");
}
}
Второй случай:
#include <vector>
int main() {
const int iterations = 1'000'000;
std::vector<const char *> c;
for (int i = 0; i < iterations; i++) {
c.push_back("qwerty");
}
}
В обоих случаях отображаемое использование памяти активным процессом составляет около 11 МБ.
Первая мысль заключалась в том, что использование памяти относится только к размеру указателей, но тогда как я могу узнать извне, сколько памяти использует определенное программное обеспечение? (Без явного вычисления размера внутри кода)
Редактировать:
Я думал, что с c.push_back("qwerty")
я каждый раз создаю новую строку. Это было моей целью. Мне удалось сделать это сейчас, изменив код таким образом:
#include <vector>
int main() {
const int iterations = 1'000'000;
std::vector<const char *> c;
for (int i = 0; i < iterations; i++) {
std::string* s = new std::string("sadadasd");
c.push_back((*s).c_str());
}
}
Это выглядит ужасно, но, по крайней мере, теперь использование памяти имеет смысл. Есть ли более элегантный способ добиться этого? (Я имею в виду без введения std::string и использования только const char*)
Пространство, занимаемое с точки зрения операционной системы, вероятно, будет отличаться от того, что фактически занято в локальном пространстве вашего процесса.
@OP Почему вы считаете, что результаты должны быть другими? Ваш код ничем не отличается от того, если бы у вас было std::vector<int>
, в первой программе вы заполнили вектор миллионом 0
, а во второй программе вы заполнили вектор миллионом 1000000
. Просто потому, что число, которое вы используете для заполнения вектора, больше, это не означает, что использование памяти увеличивается. Оба вектора по-прежнему являются векторами int
, точно так же, как оба ваших вектора являются const char *
.
Выглядит правильно. Около 8 МБ (вероятно, ровно 8 МБ, если используются большие страницы) указателей, 1 МБ стека, 2+ МБ в основном пустого пространства, содержащего начальные динамические выделения, диспетчер памяти и т. д. и образ вашей программы.
Я добавил детали в основной вопрос.
Нет, если вы хотите иметь возможность хранить уникальные строки, вам нужно будет выделить память для всех из них. Если вы не хотите хранить дубликаты, вам нужна другая структура данных.
Да, целью было иметь 1 миллион идентичных, но уникальных строк.
Прямо сейчас ваш код написан так, чтобы гарантировать, что вы столкнетесь с миллионом утечек памяти, потому что каждая из этих std::string*
s, которые вы new
, немедленно потеряны, чтобы никогда не быть delete
d. Трудно ответить, есть ли «более элегантный способ добиться этого», когда мы понятия не имеем, что такое «это». «Создайте вектор const char*
, который указывает на разные, но идентичные строки, нет, я не могу просто создать вектор std::string
s», по меньшей мере, своеобразно.
Есть ли более элегантный способ добиться чего?
«Есть ли более элегантный способ добиться этого?» - это другой вопрос, чем тот, который был задан изначально, поэтому он не по теме этого вопроса. Я предлагаю переместить его в новый пост, прежде чем кто-то решит использовать это как предлог, чтобы закрыть этот вопрос, поскольку «требует большего внимания - задает несколько вопросов одновременно». (Новый пост также должен лучше описывать ваши требования, например, объяснять, почему std::vector
приемлемо, а std::string
— нет.)
«Это» означает «Да, целью было иметь 1 миллион идентичных, но уникальных строк». написано чуть выше вашего комментария. Но это также написано в редактировании, когда я сказал, что думал, что «я думал, что с c.push_back («qwerty») я каждый раз создавал новую строку. Это было моей целью». Кроме того, я скопировал некоторый код, чтобы показать вам, чего мне нужно достичь.
За то, что я изменил вопрос, да, вы правы. Мне жаль
Я думал, что с c.push_back("qwerty") я каждый раз создавал новую строку. Если бы вы использовали vector<string>
, то это было бы так.
Указатель занимает (обычно) 8 байт.
В обоих случаях вы создаете вектор с миллионом одинаковых указателей. Итак, это 8 миллионов байтов для векторных данных. Общее использование памяти зависит от большего количества вещей, например, от того, сколько свободного места находится в векторе и сколько памяти используется остальной частью процесса.
Обе программы включают только одну копию строки. Дополнительные 44 байта — капля в море. Вторая программа могла бы даже не использовать дополнительные 44 байта, если бы они все равно были неиспользованными байтами заполнения, что вполне вероятно, поскольку ОС может распределять память только в 4096-байтовых фрагментах, называемых страницами.
Я добавил детали в основной вопрос.
Да, обе программы создают
std::vector
с миллионом копий одного и того же значения указателя.