智能指针 是封装更好用的原始指针
原始指针容易出现的问题:
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版权协议,转载请附上原文出处链接和本声明。