Подтвердить что ты не робот

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

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

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

class Person {

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

Так что obv Мне нужно реализовать метод setter для изменения переменной экземпляра 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 я бы освободил нынешнюю жену, а затем отправил сообщение о сохранении в женский объект выше, но каков правильный способ использования методов setter в С++?

4b9b3361

Ответ 1

Это зависит от того, что вы пытаетесь сделать. Во-первых, поскольку 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(), а шаблон наблюдателя - для уведомления супруг.)

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

Ответ 2

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

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

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

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

Ответ 3

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

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);