Работа с памятью
От: R1K0 Россия  
Дата: 18.06.15 11:55
Оценка:
Всем привет. Вот есть у меня некий набор классов:
typedef boost::shared_ptr<class A> APtr;
class A
{
    int a;
};

typedef boost::shared_ptr<class B> BPtr;
class B
{
    int b;
    APtr a;
};

typedef boost::shared_ptr<class C> CPtr;
class C
{
    int c;
    A a;
};


Вопросы в следующем:
1. Если я создам объект класса APtr, то он создается в куче и, по идее, его атрибут — а — тоже должен быть в куче — правильно?
2. Если я создам объект класса BPtr, то он также создается в куче, но у него есть атрибут — b — который отдельно создается в куче — и они все в куче — правильно ?
3. Ну и создаю я объект класса CPtr — он так же в куче, но он содержит объект класса А, который вроде как стековый — или он все равно в куче как часть объекта CPtr?
4. Ну и исходя из вопросов 2 и 3 — какая практика лучше — создавать объекты клаcс BPtr или CPtr, или, скорее, в каком случае какая практика лучше?
Re: Работа с памятью
От: dead0k  
Дата: 18.06.15 12:39
Оценка:
Здравствуйте, R1K0, Вы писали:

RK>Вопросы в следующем:

RK>1. Если я создам объект класса APtr, то он создается в куче и, по идее, его атрибут — а — тоже должен быть в куче — правильно?
— У APtr нет аттрибута a, у него есть какойнить приватный A * m_ptr, который указывает на объект A, размещенный на куче, у которого как раз и есть аттрибут a
объект класса APtr скорее всего будет создан на стеке, ибо нормальное его использование:
APtr smartPointerToClassA = make_shared<A>();
а не
APtr * smartPointerToClassA = new APtr( make_shared<a>() );

RK>2. Если я создам объект класса BPtr, то он также создается в куче, но у него есть атрибут — b — который отдельно создается в куче — и они все в куче — правильно ?

с учетом предыдущего:
объект BPtr создается на стеке, в нем есть указатель, адресующий объект B, созданный в отдельном куске на куче, и содержащий int B::b и B::APtr. B::APtr в свою очередь имеет указатель, адресущий объект A, созданный в каком-то другом куске кучи (и содержаший A::a)
RK>3. Ну и создаю я объект класса CPtr — он так же в куче, но он содержит объект класса А, который вроде как стековый — или он все равно в куче как часть объекта CPtr?
На стеке будет создан CPtr, у которого есть указатель, который адресует обект C, созданный на куче и содержаший в себе c и A (который в свою очередь содержит в себе A::a)
RK>4. Ну и исходя из вопросов 2 и 3 — какая практика лучше — создавать объекты клаcс BPtr или CPtr, или, скорее, в каком случае какая практика лучше?
С точки зрения архитектуры — надо смотреть конкретную архитектуру.
С точки зрения производительности:
— если у тебя их не мульены — без разницы (ну, вариант 3 может быть более дружественен к кешу, но если не мульены — то и пофиг)
— если у тебя их мульены — все варианты — какашка, нужно переделывать под контейнеры и, в зависимости от процесса обработки данных может быть выгоден как вариант 2, так и 3.

ps/
наврал про мульены и без разницы:
— если у тебя 1 объект к которому очень много обращений, то вариант 3 опять будет быстрей, так-как меньше разыменований.
Отредактировано 18.06.2015 12:43 dead0k . Предыдущая версия .
Re: Работа с памятью
От: Vamp Россия  
Дата: 18.06.15 12:48
Оценка:
RK> какая практика лучше...
Лучше:
а. Разобраться с обычными указателями и ручным управлением памятью прежде чем изучать автоматические.
б. Избегать shared_ptr как огня.
Да здравствует мыло душистое и веревка пушистая.
Re[2]: Работа с памятью
От: dead0k  
Дата: 18.06.15 12:53
Оценка:
ps/
все, на самом деле очень просто (статических членов опускаем)

1. члены объекта класса создаются там же, где и сам объект.
2. если создание объекта делается через new/make_shared — он будет создан на куче.
3. если создание объекта делается через объявление — он будет создаен на стеке, за исключением пункта 1.
Re[2]: Работа с памятью
От: Ops Россия  
Дата: 18.06.15 13:30
Оценка:
Здравствуйте, Vamp, Вы писали:

V>Лучше:

V>а. Разобраться с обычными указателями и ручным управлением памятью прежде чем изучать автоматические.
+1
V>б. Избегать shared_ptr как огня.
Только сначала разобраться почему, и когда не надо избегать
Переубедить Вас, к сожалению, мне не удастся, поэтому сразу перейду к оскорблениям.
Re: Работа с памятью
От: B0FEE664  
Дата: 18.06.15 13:52
Оценка:
Здравствуйте, R1K0, Вы писали:

RK>Всем привет. Вот есть у меня некий набор классов:

RK>
RK>typedef boost::shared_ptr<class A> APtr;
RK>class A
RK>{
RK>    int a;
RK>};

RK>typedef boost::shared_ptr<class B> BPtr;
RK>class B
RK>{
RK>    int b;
RK>    APtr a;
RK>};

RK>typedef boost::shared_ptr<class C> CPtr;
RK>class C
RK>{
RK>    int c;
RK>    A a;
RK>};
RK>


RK>Вопросы в следующем:

RK>1. Если я создам объект класса APtr, то он создается в куче и, по идее, его атрибут — а — тоже должен быть в куче — правильно?
Нет. У APtr нет члена a. Если вы просто создадите объект класса APtr, то объект типа А создан не будет:
APtr p;

— никакого объекта в куче не создаётся. Никакого объекта класса A не создаётся. Объект p класса (типа) APtr лежит на стеке и указывает в никуда.

Однако, если создать в куче объект класса A и инициализировать объект класса APtr указателем на этот созданный объект:
APtr p(new A);

, то объект p класса (типа) APtr лежит на стеке и указывает на объект класса (типа) А, который расположен в куче и который включает в себя атрибут (поле) a.

RK>2. Если я создам объект класса BPtr, то он также создается в куче, но у него есть атрибут — b — который отдельно создается в куче — и они все в куче — правильно ?

Нет. У BPtr нет члена b. Если вы просто создадите объект класса BPtr, то объект типа А создан не будет (так же как и объект класса B):
BPtr p;

— никакого объекта в куче не создаётся. Никакого объекта класса B не создаётся. Объект p класса (типа) BPtr лежит на стеке и указывает в никуда.

Однако, если создать в куче объект класса B и инициализировать объект класса BPtr указателем на этот созданный объект:
BPtr p(new B);

, то объект p класса (типа) BPtr лежит на стеке и указывает на объект класса (типа) B, который расположен в куче и который включает в себя два атрибута (поля), которые лежат в куче. При этом поле а объекта b указывает в никуда.

RK>3. Ну и создаю я объект класса CPtr — он так же в куче, но он содержит объект класса А, который вроде как стековый — или он все равно в куче как часть объекта CPtr?

Нет. CPtr не содержит объект класса А. Если вы просто создадите объект класса СPtr, то объект типа А создан не будет (так же как и объект класса C):
CPtr p;

— никакого объекта в куче не создаётся. Никакого объекта класса A не создаётся. Никакого объекта класса C не создаётся. Объект p класса (типа) CPtr лежит на стеке и указывает в никуда.

Однако, если создать в куче объект класса C и инициализировать объект класса CPtr указателем на этот созданный объект:
CPtr p(new C);

, то объект p класса (типа) CPtr лежит на стеке и указывает на объект класса (типа) C, который расположен в куче и который включает в себя атрибут (поле) a класса (типа) А, а так же атрибут (поле) c класса (типа) int.

RK>4. Ну и исходя из вопросов 2 и 3 — какая практика лучше — создавать объекты клаcс BPtr или CPtr, или, скорее, в каком случае какая практика лучше?

Для разных целей используются разные структуры.
И каждый день — без права на ошибку...
Re[2]: Работа с памятью
От: R1K0 Россия  
Дата: 18.06.15 14:02
Оценка:
Здравствуйте, B0FEE664, Вы писали:

Я видимо не совсем правильно спросил — я прекрасно знаю как работать с умными и значем про new — вопрос именно в том как в памяти располагается и все.
Re[3]: Работа с памятью
От: B0FEE664  
Дата: 18.06.15 14:05
Оценка:
Здравствуйте, R1K0, Вы писали:

RK>Я видимо не совсем правильно спросил — я прекрасно знаю как работать с умными и значем про new — вопрос именно в том как в памяти располагается и все.


Напишите создание объектов, как вы его видите, а я тогда смогу нарисовать, как они условно будут лежать.
И каждый день — без права на ошибку...
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.