C ++ уточнение управления памятью - PullRequest
0 голосов
/ 20 октября 2011

Я новичок в C ++.

У меня есть Rectangle класс. Когда я создаю Rectangle объект, подобный этому:

Rectangle R1(10,10,90,20);
  • R1 сидит в куче или стеке?
  • Если бы я создал его с помощью оператора new, только тогда он был бы в куче?

(В целом, как правильно создать объект в c ++?)

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

Rectangle* R = new Rectangle(1,1,1,1);

он будет помещен в кучу и должен быть удален с помощью delete.

Ответы [ 3 ]

4 голосов
/ 20 октября 2011
Rectangle R1(10,10,90,20);

Это создает переменную с «автоматической» продолжительностью. Он автоматически уничтожается, когда поток кода выходит из области видимости. Если это не функция, это означает, что выполнение вашего кода завершается. Обычно (но не всегда) он находится на каком-то стеке.

Rectangle* R = new Rectangle(1,1,1,1);
Rectangle* P(new Rectangle(1,1,1,1)); //rarely used

Эта часть сбивает с толку: переменная R - это указатель с автоматической продолжительностью (как выше). Он указывает на Rectangle с «динамической» продолжительностью. Обычно (но не всегда) динамический объект находится в какой-то куче. Прямоугольник уничтожается только тогда, когда вы явно уничтожаете его с помощью delete R;. Это означает, что если функция завершается, а другой копии R нет, ее невозможно удалить, и она останется в памяти до завершения вашей программы. Это называется утечкой памяти.

В C ++ динамическая память лучше всего обрабатывается с помощью умного указателя, такого как std::unique_ptr, поэтому вы не можете случайно забыть удалить его, даже если код вызывает сбой.

std::unique_ptr<Rectangle> R(new Rectangle(1,1,1,1));
1 голос
/ 20 октября 2011

Многое из того, что вы говорите, является либо деталями реализации, либо зависит от контекста. Учтите это:

// file.cpp

Rectangle r1(1,2,3,4);

int main()
{
  Rectangle r2 = r1;
  Rectangle * r3 = new Rectangle(r1);
}

Здесь r1 имеет статическое хранилище и статическое (= постоянное) время жизни , тогда как r2 имеет автоматическое хранилище и автоматическое (= объем) время жизни . Таким образом, r1 создается при запуске программы и уничтожается в конце (после возврата main), тогда как r2 создается при объявлении и уничтожается в конце своей области видимости (то есть область действия тела функции в данном случае).

Указатель r3 указывает на Rectangle объект динамическое хранилище и динамическое (= ручное) время жизни . Объект *r3 оживает в выражении new, и он будет уничтожен только по запросу пользователя через соответствующее выражение delete (или, возможно, ручной вызов деструктора). Так как мы не уничтожаем его, на самом деле это утечка .

Ничего не известно о памяти , используемой *r3, за исключением того, что эта память выделяется статической функцией-членом Rectangle::operator new(), если она существует, или иным образом глобальной функцией выделения ::operator new , Память глобальной версии обычно называется «бесплатным хранилищем».

(Все три объекта r1, r2 и *r3 предположительно равны, поскольку r2 и *r3 созданы как копии r1.)

Ситуация становится еще интереснее, если учесть переменные-члены: struct Foo { Rectangle r; };.

0 голосов
/ 20 октября 2011
  1. R1 создается с автоматической продолжительностью хранения. Это означает, что на практике он будет размещен в стекоподобной структуре. Это не должно быть в виду, «стек» просто удобен и распространен. Вам нужно позвонить new (или malloc, если вы действительно хотите по какой-то глупой причине ... не делать), чтобы динамически распределять память.

  2. См. Выше.

  3. Да, все, что вы new должны delete. Как правило, класс будет управлять этим для вас. Взять, к примеру, std::vector<T>. Вы выделяете vector в стеке, но внутренние данные (т. Е. Массив T) распределяются динамически. Когда vector выходит из области видимости, он delete [] представляет собой динамически распределенный массив для вас в своем деструкторе, позволяя вам оставаться приятно неосведомленным о базовых деталях управления памятью.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...