2011-12-20 93 views
12

我对C++有点新,并且一直在使用Obj-C和Java进行编程。C++:关于内存管理

说,我有一个类:

class Person { 

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

所以OBV我需要实现一个setter方法来改变妻子的实例变量。

像这样:

Person::SetCurrentWife (Wife *new_wife) { 

    current_wife = new_wife; 
} 

这将是一个shalllow副本。

因此,从主回路或我称之为地方:

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

所以我很困惑:会不会有内存泄漏吗?我应该在这里还是在Person的析构函数中删除妻子对象?在Obj-C中,我会释放当前的妻子,然后向上面的妻子对象发送保留消息,但在C++中执行setter方法的正确方法是什么?

+10

因为你是新的C++,听从这个建议:不要使用'new','delete',或指针。作为一个例外,你可能会在智能指针的构造函数中使用'new',但是只有在确定你确实需要动态存储之后才能使用'new'。 – 2011-12-20 13:29:11

+4

Kerrek忘了推荐[一个很好的入门C++的书(http://stackoverflow.com/q/388242/46642):) – 2011-12-20 13:31:48

+4

在OO你不OBV需要一个二传手,你需要的功能,让对象做些什么(离婚,再婚)。安装者可能很方便,但他们不是。 – stefaanv 2011-12-20 13:34:08

回答

4

您应该使用智能指针。

如果您使用常规指针,请谨慎操作!

您应该delete旧的current_wife成员都在析构函数和set方法上。设置一个新的妻子会导致旧的内存泄漏,因为指向分配内存的指针丢失(除非你在课堂外管理内存 - 见下文)。

但即使这样做,您仍需确保班级以外的人不会删除该成员。你必须决定内存管理是留给班级还是留给班级以外的人,并坚持下去。

+3

-1因为这只是一个糟糕的建议。如果智能指针实现所需的生命期语义,我会感到非常惊讶 - 你真的不相信我的妻子在我之前死亡是不可能的(或者说我的死亡会引发她的死亡),对吗? – 2011-12-20 14:15:13

+0

@JamesKanze为什么会这样呢?使用智能指针会限制你事先删除妻子对象,还是在人死后删除? – 2011-12-20 14:29:01

+0

它依赖于智能指针,但是如果删除由任何标准智能指针管理的内容,则表示您处于未定义的行为状态。如果你使用'shared_ptr',特别是对象的生命周期不在你手中。 – 2011-12-20 14:31:48

1

智能指针可以帮助你

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

这听起来像是一场灾难。 'shared_ptr'工作的情况很少,我怀疑这不是其中之一。出于两个原因:首先,“妻子”也可能知道她是谁的妻子,所以你有一个周期(并且你需要一个周期,因为如果“妻子”发生什么事情,必须通知当前配偶)。其次,“妻子”的一生当然不取决于配偶的一生 - 如果“妻子”死了,她不应该因为配偶碰巧指向她而保持活力。 – 2011-12-20 14:13:47

+0

@JamesKanze这就是为什么有'boost :: weak_ptr'我猜。它允许打破循环和安全通知死亡物体。 – cheind 2011-12-20 14:23:35

+0

@ChristophHeindl那么哪些指针应该很弱,哪些不是? 'boost :: weak_ptr'是一种破解,并且通常不可用。 – 2011-12-20 14:29:37

7

这取决于你想要做什么。首先,Kerrek SB 评论说,如果值语义可以是 ,则不需要使用指针:如果Wife是可复制和可分配的,则几乎没有原因 会动态分配它。在这种情况下,然而,我猜 WifePerson派生(尽管也许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 功能)。