STL中我们可以使用智能指针来减少内存泄露,比如unique_ptr。当unique_ptr离开作用域,指针所包含的内容会被释放。但需要注意的是,其使用不当也一样会造成内存泄露。
情况一:没有正确使用release函数
#include <iostream>
#include <memory>
#include <vld.h>
using namespace std;
int main()
{
unique_ptr<int> ptr(new int(10));
int *p = ptr.release();
return 0;
}
运行结果如下:
用vld可以检测出其存在内存泄露。这是因为调用release函数后,仅仅会释放对指针的控制权,不会释放资源。所以如果不用另一个智能指针来保存release返回的指针,程序就要负责资源的释放。
调用release函数后,要想不内存泄露,可以把代码改成如下所示。把控制权转移给ptr2,ptr2离开作用域时,会自动释放资源,所以不会内存泄露。
#include <iostream>
#include <memory>
#include <vld.h>
using namespace std;
int main()
{
unique_ptr<int> ptr(new int(10));
unique_ptr<int> ptr2(ptr.release());
return 0;
}
或者改成下面这样,手动delete,也不会内存泄露:
#include <iostream>
#include <memory>
#include <vld.h>
using namespace std;
int main()
{
unique_ptr<int> ptr(new int(10));
int *p = ptr.release();
if (NULL != p)
{
delete p;
p = NULL;
}
return 0;
}
改成上面的两种代码后,运行程序可以看到vld是真的不会报内存泄露了:
情况二:没有释放指向对象里面成员变量的内存
#include <memory>
#include <vld.h>
#include<memory>
using namespace std;
class Student
{
public:
Student()
{
m_name = new char[20];
num = 0;
}
private:
char *m_name;
int num;
};
int main()
{
unique_ptr<Student> ptr(new Student());
return 0;
}
运行结果如下:
可以看到内存泄露了,这是因为没有释放Student的成员变量m_name的空间
可以给Student增加析构函数,改成:
#include <memory>
#include <vld.h>
#include<memory>
using namespace std;
class Student
{
public:
Student()
{
m_name = new char[20];
num = 0;
}
~Student()
{
if (NULL != m_name)
{
delete [] m_name;
m_name = NULL;
}
}
private:
char *m_name;
int num;
};
int main()
{
unique_ptr<Student> ptr(new Student());
return 0;
}
或者改成下面这种形式:
#include <memory>
#include <vld.h>
#include<memory>
using namespace std;
class Student
{
public:
Student()
{
m_name = new char[20];
num = 0;
}
public:
char *m_name;
int num;
};
void release_student(Student *student) {
if (!student) {
return;
}
if (student->m_name) {
delete[] student->m_name;
}
delete student;
}
int main()
{
unique_ptr<Student, decltype(release_student)*> ptr(new Student(), release_student);
return 0;
}