C++11:智能指针

常见的内存问题:

  • 重复释放同一块内存会导致程序运行崩溃
  • 没有及时释放不再使用的内存资源,造成内存泄漏,程序占用的内存资源越来越多
  • 有些内存资源已经被释放,但指向它的指针并没有改变指向(成为了野指a

为什么要用智能指针方便和安全的使用动态内存智能指针的行为类似于常规指针 

智能指针的作用:智能指针可以在适当时机自动释放分配的内存,可以很好地避免“忘记释放内存而导致内存泄漏”问题。

头文件:#include<memory> 

  • shared_ptr  允许多个指针指向同一个对象
  • unique_ptr  独占这个对象
  • weak_ptr  是一种弱引用指向shared_ptr所管理的对象 

 shared_ptr类:

shared_ptr类似vector,也是一个模板,创建的方式:

	int a = 10;
    //指向int 的shared_ptr
	shared_ptr<int>p(&a);//指向a
    //指向 int的vector 的shared_ptr
	shared_ptr<vector<int>>p1;//默认初始化为nullptr

shared_ptr类的常用成员函数:

成员方法功能
operator=()重载赋值号,可以相互赋值
operator*()获取shared_ptr所指的数据
operator->()获取内部成员,等价于(*p).men
swap()交换两个相同类型 shared_ptr 智能指针的内容
reset()当函数没有实参时,该函数会使当前 shared_ptr 所指堆内存的引用计数减 1,同时将当前对象重置为一个空指针;当为函数传递一个新申请的堆内存时,则调用该函数的 shared_ptr 对象会获得该存储空间的所有权,并且引用计数的初始值为 1。
get()获得 shared_ptr 对象内部包含的普通指针
use_count()返回同当前 shared_ptr 对象(包括它)指向相同的所有 shared_ptr 对象的数量
unique()判断当前 shared_ptr 对象指向的堆内存,是否不再有其它 shared_ptr 对象再指向它

make_shared<T>(args)

返回一个shared_ptr,指向一个动态分配的类型为T的对象,使用args初始化此对象。

shared_ptr的创建的方式:

	shared_ptr<int>b1;
	shared_ptr<int>p;//默认初始化
	shared_ptr<int>p1(b1);//传参
	shared_ptr<int>p2(new int(42));//指向一个值为42的int
	shared_ptr<int>p3 = make_shared<int>(10);//使用make_shared初始化

make_shared的使用:

shared_ptr的最安全的分配和使用动态内存的方法,make_shared会返回指向此对象的shared_ptr

    shared_ptr<int>k1 = make_shared<int>(40);
	shared_ptr<string>k2 = make_shared<string>(5, '3');//字符串可以这样使用 33333
	shared_ptr<int>k3 = make_shared<int>();//默认为0

 常用auto与make_shared一起使用

    auto g1 = make_shared<int>(50);
	auto b(g1);//shared_ptr的拷贝

 当一个shared_ptr的计数器变为0时,它会自动释放自己管理的对象

    auto g1 = make_shared<int>(50);
	auto b(g1);//shared_ptr的赋值
	auto kk = make_shared<int>(100);//kk指向的int只有一个引用者
	kk = b;//给kk赋值,指向另一个内存,r原来指向对象的对象计数器-1==0,当计数器等于0时,自动释放内存

shared_ptr自动销毁所管理的对象:

当指向一个对象的最后一个shared_ptr被销毁时,shared_ptr会调用析构函数来完成销毁。shared_ptr的析构函数会递减它所指向对象的引用计数,引用计数为0,析构函数就会销毁对象,并释放内存。注意:shared_ptr还会自动释放相关联的内存

不要把普通指针和智能指针混合使用:

智能指针的使用:

void text(shared_ptr<int>p)//值传递,会传递一个拷贝,拷贝时会增加引用计数
{

}
int main()
{
	shared_ptr<int>p1(new int(20));//p指向一个数据,引用计数为1
	text(p1);//拷贝时,引用计数+1,变为2
	//执行完后引用计数-1,变为1
	int i = *p1;//引用计数为1,没被销毁,正确
	return 0;
}

以下为错误示范:

void text(shared_ptr<int>p)//值传递,会传递一个拷贝,拷贝时会增加引用计数
{

}
int main()
{
	int* a(new int(20));//一个普通指针
	text(shared_ptr<int>(a));//合法但内存会被释放
	int j = *a;//a的内存被释放,a为空悬指针
	cout << *a << endl;//该值为未定义
	return 0;
}

不要用get函数去初始化另一个智能指针或为智能指针赋值

	shared_ptr<int> p(new int(20));//引用计数为1
	int* q = p.get();
	{
		shared_ptr<int>(q);//指向相同的内存
	}
	//程序块结束后,q被销毁,指向的内存被释放
	int foo = *p;//未定义,p指向的内存被销毁

 智能指针注意事项:

  • 不使用相同的内置指针初始化或(reset)多个智能指针
  • 不使用get()初始化或reset另一个指针指针
  • 不delete get()返回的指针
  • 使用了get()初始化的指针,当最后一个shared_ptr销毁时,指针变为无效
  • 使用的智能指针管理的资源不是new分配的内存,需要传递一个删除器

unique_ptr 

一个unique_ptr只拥有它所指向的一个对象

由于只能拥有一个对象,那么unique_ptr,不能使用普通的拷贝和赋值操作

在c++11种没有make_unique,来构造一个unique_ptr,但在c++14种新加了 make_unique

unique_ptr的创建:

	unique_ptr<int>p(new int(20));
    unique_ptr<int>p2();//空指针
    unique_ptr<int>p3(nullptr);//空指针

无法赋值和拷贝:

	unique_ptr<int>p(new int(20));
	unique_ptr<int>p1(p);//报错
	unique_ptr<int>p2;
	p2 = p;//报错
函数功能
unique_ptr<T> u1空unique_ptr
unique_ptr<T,D> u2u2会使用一个类型为D的对象来代替delete
unique_ptr<T,D> u2(d)空unique_ptr,使用一个类型为D的对象来代替delete
u=nullptr释放u指向的对象
u.release()u放弃对指针的控制权,返回指针,并将u置为空
u.reset()释放u所指的对象
u.reset(q)提供了内置指针q,令u指向这个对象,否则将u置为空

unique_ptr不能拷贝和赋值,但可以把控制权转移:

	unique_ptr<int>p(new int(20));
	unique_ptr<int>p2(p.release());//将控制权转移给p2,把p置空

    unique_ptr<int>p5(new int(30));
	unique_ptr<int>p4(move(p5));//使用移动构造函数,p4获得p5的控制权,把p5置为空指针

传递unique_ptr参数和返回unique_ptr

不能拷贝unique_ptr,但可以拷贝或赋值一个将要销毁的unique_ptr

编译器对这种要返回的对象将要销毁,编译器会执行移动构造函数。

unique_ptr<int> text(int p)
{
	return unique_ptr<int>(new int(p));//返回一个unique_ptr
}
unique_ptr<int> text2(int p)
{
	unique_ptr<int>k(new int(p));
	return k;//返回一个局部变量的拷贝
}

weak_ptr

weak_ptr是一种不控制所指向对象生存期的智能指针,指向由shared_ptr管理的对象。 weak_ptr 类型指针的指向和某一 shared_ptr 指针相同时,weak_ptr 指针并不会使所指堆内存的引用计数加 1;同样,当 weak_ptr 指针被释放时,之前所指堆内存的引用计数也不会因此而减 1,weak_ptr是一种“弱”共享对象。

成员函数功能
weak_ptr<T> w空的weak_ptr可以指向类型为T的对象
weak_ptr<T> w(sp)shared_ptr sp 指向相同对象的weak-ptr
w=pp可以是一个shared_ptrh或一个weak_ptr,赋值后共享对象

w.reset()

将w置空
w.use_count()于w共享对象的shared_ptr的数量
w.expired()w.use_count()为0返回true,否则返回false
w.lock()w.expired()为true,返回一个空的shared_ptr,否则返回w指向的对象

weak_ptr<T> 模板类中没有重载 * 和 -> 运算符,这也就意味着,weak_ptr 类型指针只能访问所指的堆内存,而无法修改它 

weak_ptr指针的创建

	weak_ptr<int>gg();//空的weak_ptr
	shared_ptr<int>p(new int(5));
	weak_ptr<int>k(p);//指向sharead_ptr对象,弱共享,引用计数不会改变

weak_ptr成员函数的使用

	shared_ptr<int>p(new int(5));
	weak_ptr<int>k(p);//指向sharead_ptr对象,弱共享,引用计数不会改变
	shared_ptr<int>k1(k.lock());//k1和k共享对象
	int i = k.use_count();//获取与k共享的shared_ptr的数量
	k.reset();//将k置空

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C++11引入了智能指针,它们是一种用于管理动态分配的内存的工具。智能指针可以自动处理内存的释放,避免了手动释放内存的麻烦和可能的内存泄漏。C++11提供了三种类型的智能指针:unique_ptr、shared_ptr和weak_ptr。 1. unique_ptr:unique_ptr是一种独占所有权的智能指针,它确保只有一个指针可以访问给定的资源。当unique_ptr超出作用域或被重新赋值时,它会自动释放所管理的资源。以下是一个unique_ptr的示例: ```cpp #include <memory> int main() { std::unique_ptr<int> ptr(new int(10)); // 使用ptr指向的资源 std::cout << *ptr << std::endl; // unique_ptr会在超出作用域时自动释放资源 return 0; } ``` 2. shared_ptr:shared_ptr是一种共享所有权的智能指针,它可以被多个指针同时访问同一个资源。shared_ptr使用引用计数来跟踪资源的使用情况,当最后一个shared_ptr超出作用域时,资源会被释放。以下是一个shared_ptr的示例: ```cpp #include <memory> int main() { std::shared_ptr<int> ptr1(new int(10)); std::shared_ptr<int> ptr2 = ptr1; // 使用ptr1或ptr2指向的资源 std::cout << *ptr1 << std::endl; std::cout << *ptr2 << std::endl; // shared_ptr会在最后一个引用超出作用域时释放资源 return 0; } ``` 3. weak_ptr:weak_ptr是一种弱引用的智能指针,它可以指向shared_ptr所管理的资源,但不会增加引用计数。weak_ptr主要用于解决shared_ptr的循环引用问题。以下是一个weak_ptr的示例: ```cpp #include <memory> int main() { std::shared_ptr<int> ptr1(new int(10)); std::weak_ptr<int> ptr2 = ptr1; // 使用ptr1或ptr2指向的资源 std::cout << *ptr1 << std::endl; if (auto sharedPtr = ptr2.lock()) { // 使用ptr2指向的资源 std::cout << *sharedPtr << std::endl; } // weak_ptr不会影响资源的生命周期 return 0; } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值