老规矩,先问题后文章:
为什么要有智能指针以及它的好处是什么、智能指针是在怎么工作的、智能指针的操作;
1:为什么要有智能指针:
要知道,内存泄漏是非常严重的后果,如果new出来的空间没在合适的时间delete,那么很容易出现bug或者内存泄漏,而合适地用new和delete又是一个特别难的工作,所以C++就推出了智能指针这个概念,其是为了方便程序员管理内存。
大量使用智能指针代替new、delete函数,可以大大地提高程序的稳定性;
2:智能指针是怎么工作的:
个人理解为智能指针是将原始指针封装起来,并结合new、delete、一些必要的函数,因为有delete的参与,所以智能指针可以在适合的时候自动释放;
先介绍智能指针的两个主力:unique、share
unique:
我们先定义一个unique指针:
#include
#include
#include
int main() {
{
std::unique_ptr a = std::make_unique(10);
}
}
为了某种目的,本菜用一个空作用域将指针围起来;
如果程序出了空作用域,那么系统会自动调用delete函数,将指针和其指向的内容给释放掉;
如果我们将a赋值给其他指向同类型的unique指针:
#include
#include
#include
int main() {
{
std::unique_ptr a = std::make_unique(10);
auto b=a;
}
}
报错:
因为unique的一个特征就是不能有两个指针指向同一个对象,这个特性也导致unique指针不能作为实参传入函数当中;
这种看似无法理解的机制是因为如果多个unique指针指向同一个对象,当其中一个unique指针被释放时,其对象也会被释放,也就是说其他指向这个对象的指针将成为野指针;
下面来看看智能指针自动释放的功能:
#include
#include
#include
class temp {
public:
temp() {
std::cout << "Created" << std::endl;
}
~temp() {
std::cout << "Destroyed" << std::endl;
}
};
int main() {
{
std::unique_ptr a = std::make_unique();
}
}
运行结果:
这里我们没有用delete函数,系统就自动释放指针和指向的对象了;
如果我们想要将智能指针传入函数当中,那么我们就需要share指针了:
share指针允许多个share指针指向同一个对象,而且实例化一个share指针时会多出一些内存开销,这些内存会实现一个功能,即引用计数,这个引用计数会记录有多少个share指针指向该对象,当引用计数发现没有指向该对象的指针时,系统就会将该对象释放;
看下面这段代码:
#include
#include
#include
class temp {
public:
temp() {
std::cout << "Created" << std::endl;
}
~temp() {
std::cout << "Destroyed" << std::endl;
}
};
int main() {
std::shared_ptr a = std::make_shared();
{
std::shared_ptr b = a;
}
getchar();
}
运行结果【程序停留在getchar()部分】
说明b指针的释放并没有导致b指向的对象被释放,因为还有一个a指针指向该对象,引用计数不为0;
但是如果我们这样写:
#include
#include
#include
class temp {
public:
temp() {
std::cout << "Created" << std::endl;
}
~temp() {
std::cout << "Destroyed" << std::endl;
}
};
int main() {
{
std::shared_ptr a = std::make_shared();
{
std::shared_ptr b = a;
}
}
getchar();
}
运行结果为:
因为到达getchar函数时,两个指针都被释放了,所以对象也跟着被释放了;
然后来谈谈引用计数:
引用计数说白了,就是检测有多少个share指针指向同一个对象,如果为0的话,那么就将调用delete函数将对象清除;
有以下几种情况可以改变引用计数:
(1)当指针方向改变时,引用计数会减小;
(2)当指针被释放时,引用计数会减小;
(2)当指针指向对象时,引用计数会增加;
看以下代码【use_count()函数是share内置的一种函数,功能是返回有多少个share指针指向该对象】
#include
#include
#include
class temp {
public:
temp() {
std::cout << "Created" << std::endl;
}
~temp() {
std::cout << "Destroyed" << std::endl;
}
};
void get(std::shared_ptr mid) {
std::cout << mid.use_count() << std::endl;
}
int main() {
{
std::shared_ptr a = std::make_shared();
get(a);
{
std::shared_ptr b = a;
get(b);
}
get(a);
}
getchar();
}
运行结果:
这是因为将a传入函数时,函数会生成一个share指针形参,并将a赋值给形参,这个时候就有两个share指针指向同一个对象了,而将a赋值给b时,又多出一个,当b超出作用域时,就少了一个;
当然,有时候我们会希望用一个指向由share指针指向的对象时,不引起share指针引用计数的改变,那么我们就可以用weak指针了,这个指针是为了搭配share指针而产生的。如果我们将上述代码中的形参改为weak指针,那么运行结果为:
好了~这些就是简单的智能指针介绍了,以后本菜还会继续更新;