Использование объектов или указателей на объекты в качестве членов класса и распределение памяти - PullRequest
2 голосов
/ 09 мая 2011

Подобный вопрос был задан здесь:

Члены класса, которые являются объектами - указатели или нет? C ++

так что я буду кратким.

Скажем, у меня есть объект, который содержит три вектора stl. Правильно ли мое мышление, что если они являются постоянными членами класса, память о них будет «вместе» для всего объекта? например моя память выглядела бы как 10 блоков вектора A, 5 блоков вектора B, а затем 15 блоков вектора C. Затем однажды я вставил бы больше объектов в вектор A так, чтобы пространство исчерпало всю структуру, включая вектор B и C, переехал?

Это тогда аргумент для указателей? Или векторы внутри системы только указатель на выделенную память? Тот же вопрос будет идти для списков и т.д ...

Существуют ли эмпирические правила относительно стоимости перенаправления по сравнению со стоимостью копирования небольших объектов? Может быть, вдоль строк перенаправления 5 указателей = 1 целочисленная копия?

Спасибо

Ответы [ 3 ]

2 голосов
/ 09 мая 2011

Скажем, у меня есть объект, который содержит три вектора stl.Правильно ли мое мышление, что, если они являются постоянными членами класса, память о них будет «вместе» для всего объекта?например, моя память будет выглядеть как 10 блоков вектора A, 5 блоков вектора B, а затем 15 блоков вектора C.

Каждый vector занимает фиксированный размер в содержащем объекте, независимо от числаэлементов, хранящихся в данный момент в vector.Вполне вероятно, что value_type из vector (например, vector<int> имеет value_type int) не повлияет на размер самого содержащегося vector объекта: только количество выделенной кучи памятиvector необходимо для того, чтобы поддерживать свой объем памяти (так что они, вероятно, должны быть, скажем, 8, 16 или 32 байта каждый, но все равно, но не 10 «блоков» (какими бы они ни были), 5 блоков и 15).

Будет ли после того, как я добавлю больше объектов в вектор A, так что пространство изменится на всю структуру, включая векторы B и C, необходимо переместить?

Вставка элементовв A может привести только к перемещению существующих элементов в A (при превышении емкости).B и C никогда не могут быть затронуты.

Это тогда аргумент для указателей?Или внутренне векторы являются только указателем на выделенную память?

ДА, это аргумент ... такой хороший, что ДА, vector s уже do используют указателив непрерывную память, где хранятся фактические элементы value_type.

Тот же вопрос будет и для списков и т. д. *

ДА, list s хранят ихvalue_type элементов в куче тоже, и размер объекта, встраиваемого или полученного из list, не зависит от операций с list.

Существуют ли какие-либо практические правила относительностоимость перенаправления против стоимости копирования небольших объектов?Может быть, вдоль строк перенаправления 5 указателей = 1 целочисленная копия? enter code here

C ++ работает на слишком многих платформах, чтобы для этого существовали хорошие практические правила.Даже на процессорах, скажем, x86, различия в наборе команд, # ядрах, размерах кэша, поставщике / модели / генерации процессора и т. Д. Могут быть огромными.Косвенное обращение является наиболее дорогостоящим, если оно приводит к сбоям страницы памяти, и это очень зависит от общей картины выполнения программы на машине.Если вам интересно, тестируйте реальные компьютеры, на которых запущена программа, пока не найдете статистически значимых и стабильных результатов.

1 голос
/ 09 мая 2011

Классы коллекций реализованы внутри с помощью указателей - вам не нужно беспокоиться о том, что им не хватит места.Что касается затрат на копирование, не беспокойтесь об этом, если только вы не доказали , представив свой код , что это проблема.

0 голосов
/ 09 мая 2011

Поскольку std::vector имеют динамический размер, они не могут хранить свои элементы как члены или как массив элементов.Помните, что размер объекта известен во время компиляции.

Даже тогда есть все еще что-то, что можно сказать о неиспользовании элементов указателя.Рассмотрим этот тип:

struct fat {
    array<double, 30> data;
    array<long, 30> more_data;
    array<char, 30> too_much_data;
};

, где array может быть std::array, std::tr1::array или boost::array;это здесь просто используется в качестве замены для большого типа.Вы правы, что fat объекты будут, ну, в общем, большими.Замена членов на указатели (или динамические массивы, или любой другой моральный эквивалент) все еще преждевременна: сначала используйте объекты как есть, а затем, если они слишком большие или иным образом проблематичные, вы можете динамически распределять их вместочлены:

fat* so_much_stuff = new fat[30]();
// Better:
std::vector<fat> get_rid_of_it_already(30);

Семантика значения просто делает вещи проще;Только до тех пор, пока не будет слишком много копий, или размера, или чего-то еще (сначала измерьте) , но не раньше , вы должны использовать (динамические) контейнеры и умные указатели (которые сами следуют семантике значений).

РЕДАКТИРОВАТЬ

std::vector не является «плохим» в целом (как член или нет), см. Обсуждение с Тони в комментариях.

...