我对C ++有点新,到目前为止一直在使用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);
所以我很困惑:这里会有内存泄漏吗?我应该在这里或在Person的析构函数中删除妻子对象吗?在Obj-C中,我会释放当前的妻子,然后向上面的妻子对象发送一条保留消息,但在C ++中使用setter方法的正确方法是什么?
答案 0 :(得分:7)
这取决于你想要做什么。首先,正如Kerrek SB所做的那样
注释,如果值语义可以,你不想使用指针
apply:如果Wife
是可复制和可分配的,那么几乎没有理由
动态分配它。然而,在这种情况下,我猜测
Wife
来自Person
(虽然可能是Person
的装饰者
因为给定Person
是A的事实会更合适
Wife
可以随时间变化),甚至可能有派生类型
来自Wife
(而Person::current_wife
可能希望拥有其中一个
这些),事实上,Wife
具有同一性;你不想要副本
到处都是同一个妻子。
如果是这种情况,那么你真的必须为该协议定义一个协议
其他类与Wife
的互动。通常,寿命
Wife
不会依赖持有它的Person
(尽管它是一个。{1}}
装饰者,它可能),所以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
中可能是有意义的
功能)。
答案 1 :(得分:4)
你应该使用智能指针。
如果您使用常规指针,请务必小心!
您应该在析构函数和set方法上delete
旧的current_wife
成员。设置一个新的妻子将导致旧的内存泄漏,因为指向该分配的内存的指针丢失(除非您管理类外的内存 - 见下文)。
但即使这样做,您也需要确保班级以外的任何人都不能删除该成员。您必须决定是将内存管理留给类还是分配到类的外部,并坚持使用它。
答案 2 :(得分: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);