所以我有一个基类看起来像这样:
class base {
public:
base() {
std::cout << "We created a base!" << std::endl;
}
~base() {
std::cout << "We destroyed a base!" << std::endl;
}
};
我有一个派生类看起来像这样:
class leaks_memory : public base {
public:
leaks_memory(size_t count) :
memory(new int[count]), size_of_memory(count)
{
announce();
}
leaks_memory(const leaks_memory & lm) :
leaks_memory(lm.size_of_memory)
{
std::copy(lm.memory, lm.memory + size_of_memory, memory);
}
void swap(leaks_memory & lm) noexcept {
std::swap(lm.memory, memory);
std::swap(lm.size_of_memory, size_of_memory);
}
leaks_memory(leaks_memory && lm) {
swap(lm);
}
leaks_memory & operator=(leaks_memory lm) {
swap(lm);
return *this;
}
~leaks_memory() {
delete[] memory;
dennounce();
}
int & operator[](size_t index) {
return memory[index];
}
const int & operator[](size_t index) const {
return memory[index];
}
private:
int * memory;
size_t size_of_memory;
void announce() const noexcept {
std::cout << "We created a Leaks Memory!" << std::endl;
}
void dennounce() const noexcept {
std::cout << "We destroyed a Leaks Memory!" << std::endl;
}
};
现在,在我编写看起来像这样的代码之前,这些都不是问题:
int main() {
std::unique_ptr<base> base_ptr;
std::atomic_bool done = false;
std::thread input_thread{ [&done] {
std::getline(std::cin, std::string());
done = true;
} };
while (!done) {
base_ptr = std::make_unique<leaks_memory>(20'000);
}
input_thread.join();
return 0;
}
此代码在循环的每次迭代中泄漏20kb,因为leaks_memory
析构函数永远不会被调用!
现在,显然,我可以通过编辑base
:
virtual ~base() {
std::cout << "We destroyed a base!" << std::endl;
}
事实上,如果我在进行此更改后运行相同的代码,我就不再有此内存泄漏。
但是,如果我处于无法编辑base
课程的情况怎么办?有没有办法在不完全改变执行代码设计的情况下防止内存泄漏?
答案 0 :(得分:2)
C ++ 11智能指针具有自定义删除功能,可以放松在每个层次结构的根目录下拥有虚拟析构函数的要求。
不幸的是,此功能不易使用,因为删除器的类型是shared_ptr和unique_ptr的模板参数。因此,为了隐藏最终对象的类型,需要一些类型擦除:
void derived_deleter(base* p) { delete static_cast<derived*>(p); }
std::unique_ptr<base, decltype(&derived_deleter)> base_ptr (new derived, derived_deleter);
似乎无法使用std :: make_unique。
答案 1 :(得分:0)
如果您可以使用const
引用,则另一个选项可能是使用"most important const"
以下内容将创建对base的引用,但会调用派生的析构函数。
leaks_memory factory()
{
return leaks_memory(20'000);
}
int main()
{
//std::unique_ptr<base> base_ptr;
std::atomic_bool done = false;
std::thread input_thread{[&done] {
std::getline(std::cin, std::string());
done = true;
}};
while (!done) {
//base_ptr = std::make_unique<leaks_memory>(20'000);
const base& base_const_ref = factory();
}
input_thread.join();
return 0;
}