Вопрос о типе памяти, в которой находятся члены класса

101
05 августа 2019, 12:20

При создании массива в стеке

int stek_array [1000000];

произойдет переполнение стека, программа не скомпилируется, это понимаю.

При создании объекта

A* ob2 = new A();

ob2 будет находится в куче.

Вопрос следующий:

  1. В каком типе памяти, стек или куча, будет тогда находится ob2.m? Ведь программа скомпилируется.

  2. Раз программа скомилировалась, по идее ob.m будет находится в куче. В стеке массиву не хватило бы памяти. Но, это ведь тогда противоречит синтаксису определения массива в куче без оператора new.

  3. Если все же ob.m находится в куче, надо ли в деструктор класса добавлять удаление массива?

    delete m;

  4. Есть ли в с++ или visual studio средства посмотреть тип памяти, в которой находится та или иная переменная?

  5. Если создам объект в стеке A ob, а у класса "A" будет член int m [1000000]. В какой памяти тогда будет m? Ведь в стеке места ему не хватит

Код:

class A {
public:
    int m[10000000];
    A(){};
    ~A(){};
};
int main () {
    int stek_array [1000000];               массив в стеке -> переполнение стека -> крах программы
    int *heap_array = new int[1000000]; массив в куче, памяти хватает
    delete heap_array;                  удалили массив из кучи
    A ob;                                   ob и ob.m в стеке -> переполнение стека -> крах программы
    A* ob = new A();                        вопрос касается этой строчки
    delete ob;                          
    return 0;
}
Answer 1
  1. В куче - раз выделение памяти для объекта в куче, а массив - просто его часть.

  2. Но, это ведь тогда противоречит синтаксису определения массива в куче без оператора new.
    Почему? массив является частью объекта, который находится в куче, как единое целое. Посмотрите, чему равно sizeof(A). Вот эта память и выделяется для объекта - в данном случае она включает массив.

  3. Нет, потому что это удаление выполняется автоматически - при удалении объекта. Вот если бы у вас был член int*m; и в конструкторе для него выделялась бы память - тогда да, в деструкторе ее нужно было бы освобождать. Здесь же отдельного выделения памяти для массива нет.

  4. Да по сути и так видно, что где :) Наверное, можно - по адресам или еще как-то...
    Но я даже не могу представить ситуацию, когда объект выделен в куче, а какая-то его часть - в стеке (кроме извращения типа передаче указателя памяти, выделенной в стеке...).

"По-моему, так" (с) Пух

Answer 2

Механизм имеет много агрегатов. По вашему где находятся эти агрегаты, если механизм находится на Луне? Наверняка они, как часть механизма, вместе с ним на Луне. После уничтожения механизма, его агрегаты уничтожатся...

Если вы хотите выразить другое отношение, для этого существуют ассоциативность и наследование. Например, этот механизм может иметь и инструкцию, но инструкция вполне может находится не вместе с ним на Луне, а на Земле... Такое отношение(ассоциативность) выражать можно так.

class Mechanism {
    Mechanism() : m(nullptr) {}
    //...
private:
    direction* m;
};

Если указатель нулевой, то нет инструкции. Если он указывает на инструкцию, находящийся в обьекте Земля, то независимо от того, где находится механизм, инструкция будет находится там, где находится Земля

Answer 3
  1. В языке С++ нет такого понятия как "тип памяти". В С++ есть такое понятие, как "продолжительность хранения" (storage duration), которое говорит, как долго будет существовать память объекта, будет ли она освобождена автоматически и если будет, то когда.

    В данном случае гарантируется, что память массива A::m будет существовать ровно столько, сколько существует память охватывающего его объекта типа A. Это фактически все, что вас должно беспокоить.

    Практически же ваш массив является неотделимой встроенной частью объекта типа A. Где расположен объект типа A, там же расположен и массив A::m.

  2. В С++ нет такого понятия, как "синтаксис определения массива в куче". Невозможно определить что-то в куче. Определение можно предоставить только для именованного объекта, а объекты в куче не имеют имен. Объекты в куче создаются специальными выражениями (например, new-выражение), а не определениями.

    При этом объявление нестатического члена класса не является определением вообще. Поэтому бессмысленно пытаться судить по этому объявлению о том, как и где будет выделяться память для объекта.

  3. Нет, не надо. Вы не выполняли new-выражение, чтобы выделить память индивидуально для этого массива? Значит вам не нужно выполнять и delete-выражение для ее освобождения.

  4. Ну наверное взглянув на адрес объекта и посмотрев на карту адресного пространства процесса можно определить, где именно располагается объект. Да, для всего этого существуют системно-зависимые и реализационно-зависимые средства.

  5. Если "не хватит", значит вы и не сможете его создать. Вы же сами уже пришли к такому выводу в ходе своих экспериментов.

READ ALSO
Аналоги функций Python str и int в С++

Аналоги функций Python str и int в С++

В Python есть две функции: str и intЕсть ли возможность так переключаться между строкой и числом в C++? У меня есть a = 10

113
JavaFx TreeView и ListView скрывать элементы

JavaFx TreeView и ListView скрывать элементы

Как скрывать некоторые элементы TreeView и ListView?

147