C ++: об управлении памятью - PullRequest
       13

C ++: об управлении памятью

12 голосов
/ 20 декабря 2011

Я немного новичок в C ++ и до сих пор занимался программированием в Obj-C и Java.

Скажи, у меня есть класс:

class Person {

private:
   Wife *current_wife;
   //.....
};

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

Как это:

Person::SetCurrentWife (Wife *new_wife) {

    current_wife = new_wife;
}

Это будет копия ниже.

Так что-то из основного цикла или что-то, что я называю:

Person *some_person = new Person();
...
Wife *wife = new Wife ();
some_person->SetCurrentWife(wife);

Так что я в замешательстве: здесь будет утечка памяти? Должен ли я удалить объект жены здесь или в деструкторе Персона? В Obj-C я освобождаю текущую жену и затем отправляю сообщение сохранения объекту жены выше, но как правильно делать методы установки в C ++?

Ответы [ 3 ]

7 голосов
/ 20 декабря 2011

Это зависит от того, что вы пытаетесь сделать.Во-первых, как прокомментировал Kerrek SB, вы не хотите использовать указатели, если семантика значений может быть применена: если Wife копируемый и назначаемый, то почти нет причин динамически выделять его.В этом случае, однако, я предполагаю, что Wife происходит от Person (хотя, возможно, более подходящим является декоратор для Person, поскольку тот факт, что данный Person isA Wife может меняться со временем), что могут быть даже типы, производные от Wife (и что Person::current_wife может захотеть содержать один из них), и что на самом деле Wife имеет идентичность;вам не нужны копии одной и той же жены повсюду.

Если это так, то вам действительно нужно определить протокол взаимодействия других классов с Wife.Как правило, время жизни Wife не будет зависеть от Person, который его держит (хотя, если это декоратор, он может), поэтому Person должен просто держать указатель на него, как вы сделали.Скорее всего, объект Wife будет иметь различные функции, которые - неявно или явно - управляют его временем жизни: у вас может быть что-то вроде:

void Wife::die()
{
    //  ...
    delete this;
}

например.В этом случае, однако, тот, кто женат на Wife, должен быть проинформирован, так что current_wife не указывает на мертвого супруга.Обычно для этого может использоваться какой-либо вариант схемы наблюдателя.(Обратите внимание, что у вас точно такая же проблема в Java; вы не хотите, чтобы Person::current_wife указывал на мертвый Wife. Поэтому вам все равно понадобится функция Wife::die() и шаблон наблюдателя для уведомления супруга.)

В подобных случаях (которые, по моему опыту, представляют подавляющее большинство динамически размещаемых объектов в C ++), единственное различие между C ++ и Java состоит в том, что в C ++ есть специальный синтаксис для вызова «деструктора»;в Java вы используете обычный синтаксис вызова функции и можете присвоить функции любое имя по вашему желанию (хотя dispose кажется широко используемым).Специальный синтаксис позволяет компилятору генерировать дополнительный код для освобождения памяти, но все другие действия, связанные с окончанием времени жизни объекта, все еще должны быть запрограммированы (в деструкторе в C ++ - хотя в этом случае это может сделатьсмысл ставить некоторые из них прямо в функцию Wife::die).

4 голосов
/ 20 декабря 2011

Вы должны использовать умный указатель.

Если вы используете обычный указатель, будьте осторожны!

Вы должны delete старый current_wife член как в деструкторе, так и в методе set. Установка новой жены приведет к утечке памяти старой, так как указатель на эту выделенную память будет потерян (если вы не управляете памятью вне класса - см. Ниже).

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

1 голос
/ 20 декабря 2011

Умные указатели могут помочь вам

using boost::shared_ptr; // or std::shared_ptr, or std::tr1::shared_ptr or something like this
class Person { 

private: 
   shared_ptr<Wife> current_wife; 
   //..... 
}; 

Person::SetCurrentWife (shared_ptr<Wife> new_wife) { 

    current_wife = new_wife; 
} 

А теперь вам вообще не следует удалять жену.

shared_ptr<Person> some_person ( new Person );
...  
shared_ptr<Wife> wife ( new Wife );  
some_person->SetCurrentWife(wife);  
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...