虚妄

C++11 智能指针 – Part 2 shared_ptr 和自定义Deleter

    笔记     CPP·翻译

原文地址

译注: 本翻译只遵循文章要表达的意图,而不会逐句翻译。

这个是一系列关于智能指针的文章,谈及的东西都是比较入门的介绍。

上一篇讲述了std::shared_ptr的基本用法。这一篇讲述的是相关的deleter。当std::shared对象超出作用域范围时,会自动调用析构函数,当引用计数为0时,会删除相关的裸指针,也就是如何使用自定义的deleter来删除std::shared引用的裸指针对象。

通常情况下是直接调用delete。

1
delete pointer;

但是当
shared_ptr指向的是数组对象时,情况就不同了。比如:

1
2
1
std::shared_ptr<int> p3(new int[12]);

此时如果还是使用默认的:

1
delete p3;

明显会导致内存泄漏,正确的是应该使用:

1
delete []p3;

上述的deleter是在构造std::shared_ptr`对象时,指定的deleter,通常我们可以自定义,比如:

1
2
3
4
5
void deleter(Sample * x)
{
std::cout << "DELETER FUNCTION CALLED\n";
delete[] x;
}

然后再传入std::shared_ptr构造函数中:

1
std::shared_ptr<Sample> p3(new Sample[12], deleter);

下面是完整的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <memory>

struct Sample
{
Sample()
{
std::cout << "CONSTRUCTOR\n";
}
~Sample()
{
std::cout << "DESTRUCTOR\n";
}
};

// deleter
void deleter(Sample * x)
{
std::cout << "DELETER FUNCTION CALLED\n";
delete[] x;
}

int main()
{
std::shared_ptr<Sample> p3(new Sample[12], deleter);
return 0;
}

输出:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
CONSTRUCTOR
CONSTRUCTOR
CONSTRUCTOR
CONSTRUCTOR
CONSTRUCTOR
CONSTRUCTOR
CONSTRUCTOR
CONSTRUCTOR
CONSTRUCTOR
CONSTRUCTOR
CONSTRUCTOR
CONSTRUCTOR
DELETER FUNCTION CALLED
DESTRUCTOR
DESTRUCTOR
DESTRUCTOR
DESTRUCTOR
DESTRUCTOR
DESTRUCTOR
DESTRUCTOR
DESTRUCTOR
DESTRUCTOR
DESTRUCTOR
DESTRUCTOR
DESTRUCTOR

作为deleter不仅仅只有上述一种函数的形式,还包括Lambda函数和函数对象。比如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Deleter
{
public:
void operator() (Sample * x) {
std::cout<<"DELETER FUNCTION CALLED\n";
delete[] x;
}
};

// 函数对象作为 deleter
std::shared_ptr<Sample> p3(new Sample[12], Deleter());

// Lambda函数作为 deleter
std::shared_ptr<Sample> p4(new Sample[12], [](Sample * x){
std::cout<<"DELETER FUNCTION CALLED\n";
delete[] x;
});

还有一种情况是,在使用资源池的情况下,无需真的释放内存块,而只是将内存或者资源返回给资源池。比如下面这个仿真内存池:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <memory>

struct Sample
{
};

// Memory Pool Dummy Kind of Implementation
template<typename T>
class MemoryPool
{
public:
T * AquireMemory()
{
std::cout << "AQUIRING MEMORY\n";
return (new T());
}
void ReleaseMemory(T * ptr)
{
std::cout << "RELEASE MEMORY\n";
delete ptr;
}
};
int main()
{
std::shared_ptr<MemoryPool<Sample> > memoryPoolPtr = std::make_shared<
MemoryPool<Sample> >();

std::shared_ptr<Sample> p3(memoryPoolPtr->AquireMemory(),
std::bind(&MemoryPool<Sample>::ReleaseMemory, memoryPoolPtr,
std::placeholders::_1));
return 0;
}

页阅读量:  ・  站访问量:  ・  站访客数: