C++ 智能指针:unique_ptr、shared_ptr、

智能指针 是封装更好用的原始指针
原始指针容易出现的问题:
1、未初始化的指针 野指针
2、多个未释放的指针 内存泄露
3、多次释放同一指针 悬空指针

第一种智能指针 unique_ptr
unique_ptr 智能指针
make_unique 智能指针 C++ 14 标准
1.唯一性:不可多次使用 unique_ptr 同时指向一个对象
2.不可复制、不可赋值
3.可以移动

第二种智能指针 shared_ptr
1.不唯一 可以多次使用 shared_ptr 同时指向一个对象
2.可以 赋值、复制、
3.可以移动
4.引用计数 指针指向对象会计数 归零 则释放内存
5.共享

演示 unique_ptr 智能指针

#include <iostream>
#include <string>
#include <vector>
using namespace std;
#include <memory>  // 智能指针



class Acc
{


private:
    // 属性
    string name {"acc"};  
    double balance {0.0};    

public:   
    Acc (string name="onne", double balance=0.0);
    ~Acc();
    bool deposit(double amount);
    void pr() const;  // 常函数
    double get_balance();

};




Acc::Acc(string name, double balance)
    :name(name), balance(balance){
        cout << "构造函数" << name << endl;
    }

Acc::~Acc(){
    cout << "析构函数" << name << endl;
}

bool Acc::deposit(double amount){
    balance += amount;
    return balance;
}

//常函数
void Acc::pr() const 
{
    cout << "name: " << name << ", balance: " << balance << endl;
}

double Acc::get_balance(){
    return balance;
}

int main()
{
    // 正常调用 构造函数 与 析构函数
    // Acc a1 {"a1", 100.0};

    // 如果不释放指针内存 则不会调用 析构函数
    // Acc *b1 = new Acc{"b1", 5.0};
    // delete b1;

    // 智能指针 unique_ptr 无需手动释放内存 智能指针会自动释放内存
    // unique_ptr<Acc> c1(new Acc{"c1",3.0});

    // 智能指针 C++ 14标准
    // 创建智能指针
    // auto p2 = make_unique<Acc>("mike", 2.0);
    // unique_ptr<Acc> p3;

    // 移动智能指针
    // // p3 = p2 // 会报错 因为唯一性 不可拷贝与赋值 只能移动 指向另一个
    // p3 = move(p2); // p2 会被设置为null 

    // 判断智能指针
    // if (! p2)  // p2 不为空 则进入
    //     cout << "p2 is null" << endl;

    // 通过智能指针 获取属性、调用类函数、
    // auto p4 = make_unique<Acc>("p4",20.0);
    // p4->deposit(10.0);  // 存入
    // p4->pr(); // 调用成员函数 常函数

    // 将智能指针放入容器
    vector <unique_ptr<Acc>> acc1;
    acc1.push_back( make_unique<Acc>("v1",21.0));
    acc1.push_back( make_unique<Acc>("v2",22.0));
    acc1.push_back( make_unique<Acc>("v3",23.0));

    // 将智能指针取出容器
    for (const auto &i :acc1)
        // 查看 每个指针指向对象的 属性2
        cout << i->get_balance() << endl;
    return 0;
}

演示:shared_ptr 智能指针

#include <iostream>
#include <string>
#include <vector>
using namespace std;


#include <memory>  // 智能指针

class Acc
{


private:
    // 属性
    string name {"acc"};  
    double balance {0.0};    

public:   
    Acc (string name="onne", double balance=0.0);
    ~Acc();
    bool deposit(double amount);
    void pr() const;  // 常函数
};




Acc::Acc(string name, double balance)
    :name(name), balance(balance){
        cout << "构造函数" << name << endl;
    }

Acc::~Acc(){
    cout << "析构函数" << name << endl;
}

bool Acc::deposit(double amount){
    balance += amount;
    return balance;
}

//常函数
void Acc::pr() const 
{
    cout << "name: " << name << ", balance: " << balance << endl;
}

void test_func(shared_ptr<Acc> p){
    cout << "引用计数:" << p.use_count() << endl;
}

int main()
{
    
    // // 创建 智能指针 
    // shared_ptr<int> p1{new int {100}};  // 指针申请内存 数据为100
    // // 查看引用计数
    // cout << "p1 查看引用计数:" << p1.use_count() << endl;
    // // 创建 智能指针 复制p1 使其 第二个指针与第一个指针同时指向一个对象
    // shared_ptr<int> p2{p1};
    // cout << "再 p1查看引用计数:" << p1.use_count() << endl;
    
    // p1.reset();  // 将指向 p1 的所有指针 释放内存
    // cout << "p1 查看引用计数:" << p1.use_count() << endl;
    // cout << "p2 查看引用计数:" << p2.use_count() << endl;

    // =============================================================================================

    // shared_ptr<Acc> p1 = make_shared<Acc>("p1", 100.0);   // p1 计数1
    // test_func(p1);                                        // p1 计数2 因为函数默认复制一份
    // cout << "p1.use_count() " << p1.use_count() << endl;  // p1 计数1 函数调用结束 计数回到了1

    // { // 当前作用域 超出作用域,则会被释放
    //     shared_ptr<Acc> p2=p1;                                // p1、p2 计数2 因为2个对象指向的是同一个地址
    //     cout << "p1.use_count() " << p1.use_count() << endl;
    //     cout << "p2.use_count() " << p2.use_count() << endl;

    //     { // 当前作用域
    //         shared_ptr<Acc> p3=p1;                            // p1、p2、p3 计数3  因为3个对象指向的是同一个地址
    //         cout << "p3.use_count() " << p3.use_count() << endl;

    //         p1.reset();                                       // 计数0 释放掉了
    //     }
    //     // 超出作用域就不能再使用了 例如现在的 p3 就无法打印验证 会编译报错
    //     cout << "p1.use_count() " << p1.use_count() << endl;
    //     cout << "p2.use_count() " << p2.use_count() << endl;  
    // }
    // cout << "p1.use_count() " << p1.use_count() << endl;

    // ==============================================================================================

    shared_ptr<Acc> p1 = make_shared<Acc>("p1", 100.0); 
    shared_ptr<Acc> p2 = make_shared<Acc>("p2", 200.0); 
    shared_ptr<Acc> p3 = make_shared<Acc>("p3", 300.0); 

    vector<shared_ptr<Acc>> acc1; // 容器 里面放置 智能指针

    // 放入实例化的智能指针
    acc1.push_back(p1);  // 因为会调用拷贝构造函数 所以引用计数为2
    acc1.push_back(p2);
    acc1.push_back(p3);

    for (auto &p:acc1){
        p->pr();
        cout << "引用计数:" << p.use_count() << endl;
    }
    return 0;
}

版权声明:本文为qq_42102546原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。