C++进阶语法——智能指针【学习笔记(五)】

文章目录

      • 1、智能指针简介
        • 1.1 原始指针(raw pointer)的⼀些问题
        • 1.2 智能指针(smart pointers)
      • 2、智能指针(smart pointers)——unique_ptr
        • 2.1 unique_ptr 的声明
        • 2.2 unique_ptr 的函数
        • 2.3 ⾃定义类型使⽤ unique_ptr
        • 2.4 unique_ptr 不⽀持拷⻉、赋值
        • 2.5 使⽤make_unique初始化(C++14标准)
        • 代码:
      • 3、智能指针(smart pointers)——shared_ptr
        • 3.1 shared_ptr的声明
        • 3.2 shared_ptr的函数
        • 3.3 ⾃定义类型使⽤shared_ptr
        • 3.4 vector和复制操作
        • 3.5 使⽤make_shared初始化(C++11标注)
        • 代码:

1、智能指针简介

1.1 原始指针(raw pointer)的⼀些问题

C++ 提供了内存管理的绝对⾃由度
------->• 分配
------->• 释放
------->• 声明周期管理
⼀些潜在严重问题
------->• 未初始化的指针(wild pointer),也就是野指针,可指向内存的任何位置
------->• 内存泄漏(memory leak),可能因为没有及时释放分配的内存空间
------->• 悬空指针(dangling pointer):指针指向已经释放的对象
所有权(ownership),引入智能指针
------->• 谁拥有指针?
------->• 何时可以删除指针?

1.2 智能指针(smart pointers)

• 也是对象
• 只能指向堆上分配的内存
⽤完后会⾃动删除
• 遵循RAII(资源获取即初始化)原则,对资源的申请释放,是一种成对操作的封装
• 几种C++ 智能指针:
------->• Unique pointers (unique_ptr)
------->• Shared pointers (shared_ptr)
------->• Weak pointers (weak_ptr)
------->• Auto pointers (auto_ptr) (已弃⽤)

  • 导入 #include
  • 在类模板(class templates)中定义
    • 对原始指针做了封装
    • 重载的操作符
      • 解引⽤(*)
      • 成员选择(->)
      • 不⽀持算数操作符(++, — —等)

创建智能指针的具体实例如下,smart_pointer 可以换成上面提到的 unique_ptr,shared_ptr,weak_ptr,ptr 是指向 Type 类别的智能指针,当运行完 {} 里面的程序时,会自动调用析构函数,会帮助我们处理堆上分配的内存空间,

C++进阶语法——智能指针【学习笔记(五)】_第1张图片

2、智能指针(smart pointers)——unique_ptr

  • unique_ptr ptr_name
    • 指向heap堆上类型 T 的对象
    • 唯⼀(unique),多个 unique_ptr 不可以指向同⼀个对象
    • 拥有指向对象的唯⼀所有权
    • 不可以复制或赋值,但可以移动
    • 指针使⽤完毕,被指向的对象会⾃动释放销毁
2.1 unique_ptr 的声明

C++进阶语法——智能指针【学习笔记(五)】_第2张图片

2.2 unique_ptr 的函数

C++进阶语法——智能指针【学习笔记(五)】_第3张图片

2.3 ⾃定义类型使⽤ unique_ptr

C++进阶语法——智能指针【学习笔记(五)】_第4张图片

2.4 unique_ptr 不⽀持拷⻉、赋值

std::move(p1):转移p1拥有的所有权,容器 vec 拥有堆上面对象的所有权,p1 会设置为空指针,

C++进阶语法——智能指针【学习笔记(五)】_第5张图片

2.5 使⽤make_unique初始化(C++14标准)

make_unique 的作用也是在堆上创建的内存空间,
auto 关键字是编译器根据 make_unique 的返回值自动帮我们判断数据类型,

C++进阶语法——智能指针【学习笔记(五)】_第6张图片

代码:
#include 
#include 
#include 
#include 

using namespace std;

class Account
{
private:
    string name {"account"};
    double balance {0.0};
public:
    Account(string name = "none", double balance = 0.0);
    ~Account();
    bool deposit(double amount);
    void printInfo() const;
    double getBalance();
};

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

Account::~Account()
{
    cout << "析构函数,name: " << name << endl;
}
bool Account::deposit(double amount)
{
    balance += amount;
    return true;
}

void Account::printInfo() const
{
    cout << "name: " << name << ", balance: " << balance << endl;
}
double Account::getBalance()
{
    return balance;
}

int main()
{
    
    // Account alice_account {"Alice", 1000.0}; // 构造函数和析构函数都会被调用

    // Account * bob_account = new Account {"Bob", 2000.0}; // 只有构造函数被调用
    // delete bob_account; // 析构函数被调用

    // unique_ptr p1 {new Account {"jams", 1000.0}}; // 构造函数和析构函数都会被调用

    // auto p2 = make_unique("mike", 2000.0); // 构造函数和析构函数都会被调用
    // unique_ptr p3;

    // // p3 = p2; // 报错,因为unique_ptr不允许拷贝,只能移动
    // p3 = move(p2); // p2 会被置为null,即空指针

    // if (! p2)
    //     cout << "p2 is null" << endl;

    // auto p4 = make_unique("Helen", 3000.0);
    // p4->deposit(1000.0);
    // p4->printInfo(); // 调用成员函数

    vector<unique_ptr<Account>> accounts;
    accounts.push_back( make_unique<Account>("alice",1000));
    accounts.push_back( make_unique<Account>("bob",500));
    accounts.push_back( make_unique<Account>("mike",1000));

    for (const auto &acc: accounts) 
        cout << acc->getBalance() << endl;

    return 0;
}

3、智能指针(smart pointers)——shared_ptr

  • shared_ptr ptr_name
    • 指向heap堆上类型为 T 的对象
    • 不唯⼀,多个shared_ptr可以指向同⼀个对象
    • 被管理对象的所有权在多个shared_ptr中共享
    • 可以复制或赋值
    • 可以移动
    • 引⽤计数(reference count)为0,被指向的对象会⾃动释放销毁
3.1 shared_ptr的声明

当超出 {} 的作用域后,堆上的对象也会自动销毁,

C++进阶语法——智能指针【学习笔记(五)】_第7张图片

3.2 shared_ptr的函数

use_count():返回引用计数的值,也就是当前堆上的对象被多少 shared_ptr 管理,
p1.reset() 并没有释放 p1 所指向的对象,因为 p2 还在指向这个对象,

C++进阶语法——智能指针【学习笔记(五)】_第8张图片

3.3 ⾃定义类型使⽤shared_ptr

C++进阶语法——智能指针【学习笔记(五)】_第9张图片

3.4 vector和复制操作

C++进阶语法——智能指针【学习笔记(五)】_第10张图片

3.5 使⽤make_shared初始化(C++11标注)

不再使用关键字 new,编译器也可以生成更高效的执行代码,

C++进阶语法——智能指针【学习笔记(五)】_第11张图片

代码:
#include 
#include 
#include 
#include 

using namespace std;

class Account
{
private:
    string name {"account"};
    double balance {0.0};
public:
    Account(string name = "none", double balance = 0.0);
    ~Account();
    void print() const;
};

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

Account::~Account()
{
    cout << "析构函数,name: " << name << endl;
}
void Account::print() const
{
    cout << "name: " << name << ", balance: " << balance << endl;
}

void test_func(shared_ptr<Account> p)
{
    cout << "p.use_count(): " << p.use_count() << endl; // 2
}

int main()
{
    // cout << "=====================" << endl;
    // shared_ptr p1 {new int {100}};
    // cout << "p1.use_count(): " << p1.use_count() << endl; // 1

    // shared_ptr p2 {p1}; // 共享所有权
    // cout << "p1.use_count(): " << p1.use_count() << endl; // 2

    // p1.reset(); // 释放所有权,但是不会销毁对象,因为p2还在使用
    // cout << "p1.use_count(): " << p1.use_count() << endl; // 0
    // cout << "p2.use_count(): " << p2.use_count() << endl; // 1


    // cout << "=====================" << endl;
    // shared_ptr p1 = make_shared("Alice", 1000.0);
    // test_func(p1);
    // cout << "p1.use_count(): " << p1.use_count() << endl; // 2

    // {
    //     shared_ptr p2 = p1;
    //     cout << "p2.use_count(): " << p2.use_count() << endl; // 3

    //     {
    //         shared_ptr p3 = p1;
    //         cout << "p3.use_count(): " << p3.use_count() << endl; // 4
            
    //         p1.reset();
    //     }
    //     cout << "p1.use_count(): " << p1.use_count() << endl; // 2
    //     cout << "p2.use_count(): " << p2.use_count() << endl; // 2
    // }
    // cout << "p1.use_count(): " << p1.use_count() << endl; // 1



    cout << "=====================" << endl;
    shared_ptr<Account> p1 = make_shared<Account>("Alice", 1000.0);
    shared_ptr<Account> p2 = make_shared<Account>("Bob", 2000.0);
    shared_ptr<Account> p3 = make_shared<Account>("Charlie", 3000.0);

    vector<shared_ptr<Account>> accounts;

    accounts.push_back(p1);
    accounts.push_back(p2);
    accounts.push_back(p3);

    for (const auto &p: accounts)
    {
        p->print();
        cout << "p.use_count(): " << p.use_count() << endl; // 1
    }
    return 0;
}

你可能感兴趣的:(C++,c++)