所以我会直截了当地说:我有一个函数可以向另一个类添加一些东西(恰好是一个类):
tower->set_weapon(new NoWeapon());
set_weapon()是塔类中的一个简单方法,它将内部变量与它接收的新的NoWeapon类相关联。
virtual void set_weapon(Weapon* weapon){ weapon_ = weapon; };
weapon_是指向武器类的指针,NoWeapon是层次结构的武器之子。当一切都说完了,塔楼就会清理一切:
weapon_->Clean();
delete weapon_;
然而,我仍然得到内存泄漏。我在VisualStudio 2013上使用vld,它在我提到的第一行检测到内存泄漏
tower->set_weapon(new NoWeapon());
知道为什么会这样,我怎么能解决它?
提前谢谢!
编辑:感谢YSC的解决方案。事实上,我没有初始化原始武器指针,但是你的想法让我重回正轨。至于unique_ptr的想法,我之前玩过它,但它不是我想要的解决方案。无论如何,谢谢你的帮助。
答案 0 :(得分:2)
我们缺少上下文信息,但基本上如果Tower::set_weapon()
被调用两次,Tower::weapon_
会被覆盖并且内存泄漏。建议:
Tower::Tower()
: weapon_(nullptr)
{}
void Tower::set_weapon(Weapon* weapon)
{
if (weapon_ != nullptr)
{
weapon_->Clean(); // should be called by Weapon::~Weapon()
}
delete weapon_;
weapon_ = weapon;
};
您还可以使用std::unique_ptr
:
class Tower
{
std::unique_ptr<Weapon> weapon_;
public:
Tower::Tower() {}
void set_weapon(std::unique_ptr<Weapon> weapon)
{
// assume Weapon::~Weapon() is fixed
weapon_ = std::move(weapon);
};
};
答案 1 :(得分:1)
注意:YSC的回答是正确的。武器应该不需要Clean
方法,因为它可以在析构函数中处理资源释放。
但是,如果对Clean
的调用确实有某些原因,您可以使用自定义删除工具将所有这些内容封装在std::unique_ptr
中。
struct weapon_cleaner
{
void operator()(Weapon* pw) const nothrow {
if (pw) {
try {
pw->Clean();
}
catch(...) {
}
}
delete pw;
}
};
using weapon_pointer = std::unique_ptr<Weapon, weapon_cleaner>;
class Tower
{
weapon_pointer weapon_;
public:
Tower::Tower() {}
void set_weapon(weapon_pointer weapon)
{
weapon_ = std::move(weapon);
};
};
这样称呼:
weapon_pointer make_machine_gun() {
return weapon_pointer(new MachineGun(),
weapon_cleaner());
}
mytower.set_weapon(make_machine_gun());