RALL原则和unique_ptr

一、RALL简介

RALL是resource acquisition is initialization的缩写,意思是”资源获取即初始化”。它是C++之父Bjarne Stroustrup提出的设计理念,其核心是把资源和对象的声明周期绑定,对象创建获取资源,对象销毁释放资源。在RALL的指导下,C++把底层的资源管理问题提升到了对象声明周期管理的更高层次。

二、RALL机制

  • 使用C++时,最让人头疼的便是内存管理,但却又正是对内存高度可操作性给了C++程序员极大自由和装逼资本。
  • 当我们在堆区new出一块内存空间,在使用完之后,如果不使用delete来释放这块资源则将导致内存泄漏,这在中大型项目中极具有破坏性。但人无完人,我们并不能保证每次都记得释放无法再次获取到且不再使用的内存,下面给出一个例子,让大家看看忘记释放资源造成内存泄漏多么恐怖!!
#include<iostream>
#include<memory>

int main()
{
    for (int i = 0; i <= 10000000; i++)
    {
        int* ptr = new int(3);
        ptr[0] = 1;
        ptr[1] = 2;
        ptr[2] = 3;
        //delete ptr    //忘记释放内存
    }
    return 0;
}

测试结果(未释放内存):
在这里插入图片描述

运行程序并打开资源管理器,可以发现这么简单的程序竟然占用了11点几的MB内存,所以大家千万要记得释放内存。

三、智能指针的介绍

在 C++ 中没有垃圾回收机制,必须自己释放分配的内存,否则就会造成内存泄露。解决这个问题最有效的方法是使用智能指针(smart pointer)智能指针是存储指向动态分配(堆)对象指针的类,用于生存期的控制,能够确保在离开指针所在作用域时,自动地销毁动态分配的对象,防止内存泄露。智能指针的核心实现技术是引用计数,每使用它一次,内部引用计数加1,每析构一次内部的引用计数减1,减为0时,删除所指向的堆内存

C++11提供了三种智能指针,使用这三种智能指针需导入memory的头文件。

  • std::shared_ptr:共享智能指针。
  • std::unique_ptr:独占智能指针。
  • std::weak_ptr:弱引用智能指针,它不共享指针,不能操作资源,是用来监视std::shared_ptr的。

四、std::unique_ptr的使用

std::unique_ptr 是一个独占型的智能指针,它不允许其他的智能指针共享其内部的指针,可以通过它的构造函数初始化一个独占智能指针对象,但是不允许通过赋值将一个 unique_ptr 赋值给另一个 unique_ptr

// 通过构造函数初始化对象
unique_ptr<int> ptr1(new int(10));
// error, 不允许将一个unique_ptr赋值给另一个unique_ptr
unique_ptr<int> ptr2 = ptr1;

std::unique_ptr不允许复制,但是可以通过函数返回给其他std::unique_ptr,还可以通过std::move来转移给其他的std::unique_ptr,这样原始指针的所有权就被转移了,这个原始指针还是被独占的。

#include <iostream>
#include <memory>
using namespace std;

unique_ptr<int> func()
{
    return unique_ptr<int>(new int(520));
}

int main()
{
    // 通过构造函数初始化
    unique_ptr<int> ptr1(new int(10));
    // 通过转移所有权的方式初始化
    unique_ptr<int> ptr2 = move(ptr1);
    unique_ptr<int> ptr3 = func();

    return 0;
}

unique_ptr的指针类有一个reset方法,函数原型如下:

void reset( pointer ptr = pointer() ) noexcept;

使用reset方法可以让unique_ptr解除对原始内存管理,也可以用来初始化一个独占智能指针。

int main()
{
    unique_ptr<int> ptr1(new int(10));
    unique_ptr<int> ptr2 = move(ptr1);

    ptr1.reset();
    ptr2.reset(new int(250));

    return 0;
}
  • ptr1.reset(): 解除对原始内存的管理。
  • ptr2.reset(new int(250)): 重新指定智能指针管理的原始内存。

如果想要获取独占智能指针管理原始地址,可以调用get()方法,函数原型如下:

pointer get() const noexcept;

获取原始地址的测试代码:

#include <iostream>
#include <memory>
using namespace std;

int main()
{
    unique_ptr<int> ptr1(new int(10));
    unique_ptr<int> ptr2 = move(ptr1);

    ptr2.reset(new int(250));
    cout << *ptr2.get() << endl;	// 得到内存地址中存储的实际数值 250

    return 0;
}

测试代码的结果:
在这里插入图片描述

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值