C++智能指针

引言

在C++中,动态内存的管理是用一对运算符完成的:new和delete。动态内存管理经常会出现两种问题:一种是忘记释放内存,会造成内存泄漏;一种是尚有指针引用内存的情况下就释放了它,就会产生引用非法内存的指针(已经释放了又去访问它),造成更加直接的严重后果。为了更加容易(更加安全)的使用动态内存,引入了智能指针在使用得当的情况下,可告别内存泄漏(智能指针使用不当同样会内存泄漏)。

建议

  1. 能使用智能指针,就不使用裸指针。
  2. 不得不使用裸指针时,使用静态代码扫描工具和内存检测工具。

智能指针

  1. 智能指针是一个可以像指针一样工作的对象,但是当它不再被使用时,可以自动删除动态分配的内存。
  2. C++11 提供了 3 种智能指针类型,它们分别由 unique_ptr 类、shared_ptr 类和 weak_ptr 类定义,所以又分别称它们为独占指针、共享指针和弱指针。
  3. unique_ptr :对象的所有权可以从一个独占指针转移到另一个指针,其转移方式为:对象始终只能有一个指针作为其所有者。当独占指针离开其作用域或将要拥有不同的对象时,它会自动释放自己所管理的对象。
  4. shared_ptr :共享指针将记录有多少个指针共同享有某个对象的所有权。当有更多指针被设置为指向该对象时,引用计数随之增加;当指针和对象分离时,则引用计数也相应减少。当引用计数降低至0时,该对象被删除。

unique_ptr智能指针

#include <memory> //在 memory 头文件中定义的

//初始化方式1
unique_ptr<int> uptr1(new int);
//初始化方式2,推荐此方式
unique_ptr<int> uptr = make_unique<int>();

动态分配的内存应该立即传递给智能指针构造函数,不要先将它赋值给指针变量,应避免以下方式:

int *p = new int;
unique_ptr<int> uptr(p);

智能指针不支持指针的算术运算,不能使用其他 unique_ptr 对象的值来初始化一个 unique_ptr,也不能将一个 unique_ptr 对象赋值给另外一个,这样的操作将导致两个独占指针共享相同对象的所有权

unique_ptr<int> uptr1(new int);
uptr1 ++;//非法
unique_ptr<int> uptr2 = uptr1; // 非法
unique_ptr<int> uptr3;
uptr3 = uptr1; // 非法

C++ 提供了一个 move() 库函数,可用于将对象的所有权从一个独占指针转移到另外一个独占指针:

unique_ptr<int> uptr1(new int);
*uptr1 = 15;
unique_ptr<int> uptr2;
uptr2 = move (uptr1) ; // 将所有权从 uptr1 转移到 uptr2
// U = move(V);

当执行move语句时,会发生两件事情:首先,当前 U 所拥有的任何对象都将被删除;其次,指针 V 放弃了原有的对象所有权,被置为空,而 U 则获得转移的所有权,继续控制之前由 V 所拥有的对象。

unique_ptr作为函数形参或者返回值

//函数使用通过值传递的形参
void fun(unique_ptr<int> uptrParam)
{
}

int main()
{
    unique_ptr<int> uptr(new int);
    *uptr = 10;
    /*不能直接通过值传递给函数传递一个智能指针。
      如果要让函数通过值接收一个独占指针,则在调用函数时,需调用 move() 函数:*/
    fun (move (uptr)); // 在调用中使用 move
}
//函数使用通过引用传递的值
void fun(unique_ptr<int>& uptrParam)
{
}

int main()
{
    unique_ptr<int> uptr(new int);
    *uptr1 = 15;
    //如果通过引用传递的方式,那就不必调用 move() 函数了
    fun (uptr1) ; //在调用中无须使用move
}
//返回指向动态分配资源的独占指针
unique_ptr<int> makeResource()
{
    unique_ptr<int> uptrResult(new int);
    *uptrResult = 55;
    //在遇到返回 unique_ptr 对象的函数时,编译器会自动应用 move() 操作以返回其值
    return uptrResult;
}
//若要删除智能指针管理的对象,同时又保留智能指针,可将其值设为 nullptr,或调用其 reset() 成员函数
uptr = nullptr;
uptr.reset();

shared_ptr 智能指针

多个 shared_ptr 智能指针可以共同使用同一块堆内存。

由于该类型智能指针在实现上采用的是引用计数机制,即便有一个 shared_ptr 指针放弃了堆内存的“使用权”(引用计数减 1),也不会影响其他指向同一堆内存的 shared_ptr 指针(只有引用计数为 0 时,堆内存才会被自动释放)。

//初始化方式1
std::shared_ptr<int> p3(new int(10));
//初始化方式2
std::shared_ptr<int> p3 = std::make_shared<int>(10);

shared_ptr有相应的拷贝构造函数和移动构造函数

//调用拷贝构造函数 
shared_ptr<int> p4(p3);
shared_ptr<int> p4 = p3;

//调用移动构造函数 
shared_ptr<int> p5(std::move(p4));
shared_ptr<int> p5 = std::move(p4);

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值