2015-12-11 104 views
1

所以我将直接切入正题:我是加入一些东西(这恰好是一个类)到另一个类的函数:C++内存泄漏的函数参数

tower->set_weapon(new NoWeapon()); 

的set_weapon()是塔类中的一个简单方法,它将一个内部变量与它接收的这个新的NoWeapon类相关联。

virtual void set_weapon(Weapon* weapon){ weapon_ = weapon; }; 

weapon_是Weapon类的指针,NoWeapon是武器的子级。当一切都说完了,塔本身清理一切:

weapon_->Clean(); 
delete weapon_; 

但是,我仍然得到内存泄漏。即时通讯使用的VisualStudio上2013 VLD,它检测到我提到

tower->set_weapon(new NoWeapon()); 

任何想法,为什么这种情况正在发生和我怎么能解决它的第一行中的内存泄漏?

预先感谢您!

编辑:感谢YSC的解决方案。事实上,我没有初始化原始武器指针,但是你的想法让我回到了正轨。

至于unique_ptr的想法,我以前玩过,但它不是我寻找的解决方案。还是要谢谢你的帮助。

+2

为noWeapon和武器提供的定义。 – ForeverStudent

+1

也许你不止一次地调用了set_weapon(),这里的代码忘了为这种情况处置先前的武器。 – nos

+0

只是猜测给定的代码量,但如果你两次调用'set_weapon',就会发生这种情况;第一件武器永远不会被删除。 – dfan

回答

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

并在方法中传递unique_ptr而不是原始指针! –

+0

@RichardHodges修复 – YSC

+2

使用'unique_ptr'也可以避免复制问题(规则三)。 –

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