Запутался по поводу освобождения памяти C ++ - PullRequest
1 голос
/ 20 июля 2011

Так что в C ++, если я создаю объект, используя new, я всегда должен освобождать его, используя delete
Например

Segment::Segment(float length)
{
    segmentLength = length;

    angle = 0.0f;
    x = Rand::randFloat(1.0f, 1.5f);
    y = Rand::randFloat(1.0f, 1.5f);

    vx = Rand::randFloat(0.0f, 1.0f); 
    vy = Rand::randFloat(0.0f, 1.0f);
    prevX = Rand::randFloat(0.0f, 1.0f);
    prevX = Rand::randFloat(0.0f, 1.0f);
};

И скажем, я использую это в другом классе, например,

this._segmentObject = Segment(2.0f);
this._segmentPointer = new Segment(2.0f);

В деструкторе этого класса я знаю, что должен вызывать delete для this._segmentPointer, однако как мне убедиться, что память освобождена для другого?

Ответы [ 7 ]

5 голосов
/ 20 июля 2011

однако, как я могу убедиться, что память освобождена для другой?

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

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

4 голосов
/ 20 июля 2011

Вещи, не выделенные с new, new[] или семейством malloc, должны быть уничтожены и «освобождены», когда объект выходит из области видимости.

Часто это просто означает, что код достиг конца блока, в котором он был объявлен, или объект, в котором он находился, был уничтожен (так или иначе).

Чтобы увидеть это в действии, вы можете сделать что-то вроде этого:

struct C {
    C()  { std::cout << "C()" << std::endl; }
    ~C() { std::cout << "~C()" << std::endl; }
};

struct B {
    B()  { std::cout << "B()" << std::endl; }
    ~B() { std::cout << "~B()" << std::endl; }
private:
    C c_;
};

struct A {
    A()  { std::cout << "A()" << std::endl; }
    ~A() { std::cout << "~A()" << std::endl; }
};

int main() {
    B *b = new B; // prints "B()", also constructs the member c_ printing "C()"
    { // starts a new block
        A a; // prints "A()";
    } // end of block and a's scope, prints "~A()"

    delete b; // prints "~B()", also destructs member c_, printing "~C()"
}

Примечание: если бы мы не делали delete b, то "~ B ()" и "~ C ()" никогда не были бы напечатаны. Аналогично, если бы c_ был указателем, выделенным с помощью new, он должен был бы быть delete 'd, чтобы напечатать "~ C ()"

3 голосов
/ 20 июля 2011

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

this._segmentObject назначается из временного объекта, который создается в стеке и удаляется, когда он выходит из области видимости.

1 голос
/ 20 июля 2011

Деструкторы для всех объектов-членов типа класса вызываются во время уничтожения первичного класса.Таким образом, ваш this объект, который размещен в стеке, будет вызывать свой деструктор, когда он выходит из области видимости.В это время любые объекты-члены типа класса вашего this объекта будут иметь свои собственные деструкторы, вызываемые в дополнение к деструктору для вашего this объекта, который будет вызывать delete для указателя члена.

Например, возьмем следующий пример кода:

#include <iostream>

using namespace std;

class A
{
        public:
                A() {}
                ~A() { cout << "Destructor for class A called" << endl; }
};

class B
{
        private:
                A a;

        public:
                B() {}
                ~B() { cout << "Destructor for class B called" << endl; }
};

int main()
{
        B b;
        return 0;
}

При запуске вывод будет выглядеть следующим образом:

Destructor for class B called  
Destructor for class A called

Таким образом, вы можете видеть это, когда b, который расположен настек выходит из области видимости в конце main, вызывается деструктор для класса B, который, в свою очередь, после выполнения тела функции-деструктора вызывает деструкторы для любого из его классов.введите объекты данных члена, что в данном случае означало бы деструктор для класса A.Следовательно, в вашем случае указатель будет вызывать delete в деструкторе для вашего this класса, а затем деструктор для _segmentObject будет вызываться после того, как деструктор для this завершит выполнение телаего деструктор.Затем после вызова всех деструкторов для нестатических объектов-членов-данных деструктор для this затем возвращает.

1 голос
/ 20 июля 2011

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

0 голосов
/ 20 июля 2011

Как уже говорили другие, вам не нужно явно что-либо делать, чтобы освободить память, используемую this._segmentObject.Как только она выйдет за рамки видимости, память будет восстановлена.

Не ясно, почему вы должны использовать Segment в обоих направлениях.Вам следует убедиться, что вы используете идиому Resource Acquisition is Initialization , так как она устраняет необходимость проверки пар new / delete.То есть просто используйте версию this._segmentObject, а не указатель.

Однако ваше приложение может не разрешить это.

0 голосов
/ 20 июля 2011

_segmentObject автоматически выделяется в стеке.Деструктор объекта будет вызываться автоматически, когда переменная выходит из области видимости.

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