Объект, созданный без нового оператора, удален в конкретном случае в C ++ - PullRequest
6 голосов
/ 02 сентября 2011

Если у нас есть следующий фрагмент кода:

MyObject my_object = MyObject(0);
my_object = MyObject(1);

Что происходит с MyObject (0)? Это удалено? Глядя на то, что я читал об этом, его следует удалять только тогда, когда мы покидаем область создания, так что, вероятно, нет. Если это так, есть ли способ явно удалить его, кроме использования указателей?

Ответы [ 4 ]

5 голосов
/ 02 сентября 2011
MyObject my_object = MyObject(0);

Эта строка создает my_object в стеке, используя конструктор MyObject, который может принять int.

my_object = MyObject(1);

Эта строка создает временный MyObject, опять же, использует тот же конструктор, что и первый.Затем это присваивается my_object путем вызова оператора присваивания.Если вы не предоставили этот оператор, то компилятор сделает для вас тот, который выполняет мелкую копию.Когда этот оператор завершается, временный MyObject выходит из области видимости, и для него вызывается деструктор.

Когда ваш my_object выходит из области видимости, он, в свою очередь, уничтожается таким же образом.Ни в коем случае вам не нужно удалять это вручную, потому что все расположено в стеке.

2 голосов
/ 02 сентября 2011

Когда речь идет о вновь создаваемых объектах, в памяти есть две основные области: стек и куча.Куча содержит все объекты, созданные динамически с новым.Эти объекты необходимо явно удалить с помощью оператора удаления.Стек зависит от области, и все объекты, определенные в стеке, будут удалены автоматически.Поскольку вы не используете new, все ваши объекты будут уничтожены, когда закончится их область действия.

При условии отсутствия оптимизации компилятора, ваш код примерно переводится в:

{
   MyObject my_object;
   MyObject tempObject0(0);
   my_Object = tempObject0;
   MyObject tempObject1(1);
   my_Object = tempObject;
}//3 objects are deleted by this point (in theory)

Также обратите внимание на разницу между

MyObject myObject(0);

и

MyObject myObject = MyObject(0);

Во втором случае создается временный объект, поэтому он будет менее эффективным.Это все, конечно, при условии отсутствия оптимизаций.В зависимости от компилятора, это может означать одно и то же.

1 голос
/ 02 сентября 2011

Термин delete имеет особое значение в C ++, поэтому использование удалено нежелательно.

MyObject my_object = MyObject(0);

В этой строке объявляется, что объект типа MyObject создан с автоматической продолжительностью хранения (т. Е. В стеке). Этот объект будет уничтожен (т.е. его деструктор будет выполнен), когда закончится область действия. В Стандарте не предусмотрено никаких положений для восстановления памяти (см. Более поздний пример).

Этот объект типа MyObject будет создан с использованием выражения MyObject(0). Этот конструктор инициализирует память, выделенную для исключительного использования.

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

my_object = MyObject(1);

Эта строка присваивает новое значение, определяемое выражением MyObject(1), уже существующему объекту my_object. Для этого создается временный тип MyObject с автоматической продолжительностью хранения. Затем выполняется оператор присваивания; если он не перегружен, он скопирует временное состояние в my_object, стирая предыдущее состояние. В конце выражения временное уничтожается (опять же, не делается никаких условий для вспоминания связанной памяти).

Примечание: MyObject(0) не «удаляется», так как он не существует, вместо этого память, в которую он записал свое состояние, используется повторно для копирования состояния из MyObject(1).


Как и было обещано, так как это, кажется, беспокоит вас, обсуждение аспектов памяти. Это зависит от компилятора, но большинство компиляторов ведут себя аналогично.

Предположим, что у нас есть следующая функция:

void f() {
  MyObject my_object = MyObject(0);

  {
    my_object = MyObject(1);
    do_something(my_object);
  }

  {
    my_object = MyObject(2);
    do_something(my_object);
  }
}

Сколько места требуется в стеке?

  • Мы предполагаем, что он выполняет прямое построение на первой строке
  • Мы предполагаем, что компилятор недостаточно умен, чтобы выполнять раскраску стека (например, Clang этого не делает)

С этим допущением требуется место для 3 MyObject.

  • MyObject my_object = MyObject(0);: my_object нужно жить до конца функции
  • my_object = MyObject(1);: временная потребность должна быть создана
  • my_object = MyObject(2);: временная потребность должна быть создана

Пространство стека восстанавливается в конце выполнения функции.

Если компилятор был достаточно умен, чтобы выполнять Stack Coloring, тогда два временных (которые никогда не нужны вместе) могли бы использовать одну и ту же область памяти, таким образом снижая требования к пространству до 2 MyObject.

Интеллектуальный оптимизатор также может, возможно, напрямую встраивать MyObject(1) и MyObject(2) непосредственно в my_object (если он может доказать, что эффекты будут такими же, как создание временного объекта и затем его копировать), тем самым уменьшая Требуемое пространство до 1 MyObject.

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

int main() { int i = 0; for (; i < 1000; ++i); return i; }

, которые тривиально оптимизированы для:

int main() { return 1000; }

(обратите внимание, как исчезло i)

Как вы можете заметить ... на самом деле очень трудно догадаться, на что способен компилятор / оптимизатор. Если у вас действительно жесткие требования к памяти, то (возможно, на удивление) лучше всего заменить блоки на функции.

1 голос
/ 02 сентября 2011

1-я строка создает временный объект, и этот объект присваивается my_object. Во 2-й строке создается временный объект, который присваивается my_object.

Так что есть только один объект my_object

Нам не нужно думать о временном объекте. Ответственность за обработку временного объекта лежит на компиляторе.

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