C++ 11提供的智能指针有:shared_ptr、unique_ptr、weak_ptr。在 头文件 memory 中。一、new delete 直接管理内存1、初始化string * ps = new string // 初始换为一个空string int * pi = new int ;//pi 指向一个...
C++ 11提供的智能指针有:shared_ptr、unique_ptr、weak_ptr。在 头文件 memory 中。
一、new delete 直接管理内存
1、初始化
string * ps = new string // 初始换为一个空string
int * pi = new int ;//pi 指向一个未初始化的int,*pi 未定义
int * pi = new int(1024); // pi 指向的对象值为1024
string *ps = new string(10,'9') ; // *ps 为"9999999999"
vector<int> *pv = new vector<int>{0,1,2,3,4,5,6,7,8,9};
2、释放delete
int i, *pi1 = &i, *pi2 = nullptr; double *pd = new double(33), *pd2 =pd; delete i; // 错误,, i不是一个动态分配的指针 delete pi1; // 未定义错误, pi1指向一个栈内存指针 delete pd; //正确 delete pd2; //未定义错误, pd2指向的内存已经被释放 delete pi2; //正确:不能释放一个空指针
delete 之后应该重置指针,
int *p(new int(42)); auto q =p; delete p; p=q=nullptr
3、使用new delete 管理内存常出现的问题
没有delete内存,造成内存泄漏
使用已经释放掉的对象
同一块内存释放两次
二、shared_ptr:
允许多个指针指向同一个对象。
定义与初始代码如下:
// 定义shared_ptr ,默认初始化为空指针 shared_ptr<string> p1; shared_ptr<list<int>> p2; // make_shared 函数, 头文件 memory // 返回一个shared_ptr, // make_shared<T>(args) 使用args初始化对象 shared_ptr<int> p3 = make_shared<int>(42); shared_ptr<string> p4 = make_shared<string>(10,'9') // "9999999999" shared_ptr<int> p5 = make_shared<int>(); //初始化为 0
和new 结合初始换
shared_ptr<int>p2(new int(42));
// 不能混淆普通指针和只能指针
shared_ptr<int> p1 = new int(1000); // 错误
shared_ptr<int> p2(new int(1024)); // 正确
// 错误
shared_ptr<int> clone(int p) {
return new int(p);
}
// 正确
shared_ptr<int> clone(int p) {
return shared_ptr<int>(new int(p));
}
shared_ptr的拷贝和赋值、自动释放
引用计数; 当对象不再使用时,shared_ptr 会自动释放动态对象;
auto p = make_shared<int>(42); //p指向的对象只有p一个引用者 auto q(p); // 递增一个引用计数 auto r = make_shared<int>(42); //引用计数为1 r=q ; // 给r赋值; r原来指向的对象引用计数减1; q指向的对象引用计数+1; r原来指向的对象没有引用,自动释放
当引用计数为0是,内存会被释放,当普通指针 和智能指针混用是可能会出现错误。
// 一个函数,参数为 shared_ptr<int>
void process(shared_ptr<int> ptr) {A
// 使用ptr
}// ptr离开作用于,销毁释放
/******** 正确 ********/
shared_ptr<int> p(new int(42)); // 引用计数为1
process(p); // 参数作为值传递,在函数内部引用计数为2,之后为1
int i = *p; //内有问题, 引用计数值为1;
/********* 错误 ********/
int *x(new int(1024)); // 这是一个普通的指针
process(x) ; // 错误,普通指针不能转换为 shared_ptr<int>
porcess(shared_ptr<int>(x)); //合法,但是危险,函数结束后,会释放内存
int j =*x ; // 错误,此时内存已经被释放
谨慎的使用get() 函数,只有保证内存不被释放的前提现使用。
不能用get 初始化另一个智能指针,或为另一个智能指针赋值
// 谨慎使用 get() 函数
shared_ptr<int> p(new int(42)); // 引用计数为1
int * q = p.get(); // 合法,但是保证内存释放的时机
{// 程序块
// 不要使用get() 对另一个智能指针初始化,这样对同一块内存,有多个计数
shared_ptr<int>(q);
}// q被销毁释放
int foo = *p; // 此时p所指向的内存已经被释放
在发生异常时,智能指针也能保证内存被释放
// 使用 new 分配内存,应当注意由于分支 和 异常造成的内存泄漏
void f()
{
int *ip = new int(42); // new 动态分配
// 发生异常
delete ip; // 之前发生异常,这里可能造成内存泄漏
}
// 使用智能指针, 在发生异常时,内存也会被释放
void f()
{
shared_ptr<int> sp (new int(42)); // 分配一个新对象
// 发生异常
}// 在函数结束时,shared_ptr 被销毁,同时释放指向的内存
资源管理《c++primer》:

三、unique_ptr:
独占,同一时间只有一个智能指针可以指向这个对象。
不支持普通的拷贝,和赋值
unique_ptr<string> p3 (new string ("auto")); //#4
unique_ptr<string> p4; //#5
p4 = p3; // 出错
unique_ptr<string> p4(p3); //出错:不支持拷贝
unique_ptr<string> p2(p1.release()) // release 将p1置为空
unique_ptr<string> p3(new string("Trex"));
// 将所有权从p3转移给p2
p2.reset(p3.release());

四、weak_ptr
不控制所指向对象生存期。
指向由一个shared_ptr管理的对象(由shared_ptr管理生命周期)
将一个weak_ptr绑定到一个shared_ptr不会改变shared_ptr的引用计数

// 初始化
auto p = make_shared<int>(42);
weak_ptr<int> wp(p); // 若共享,p的技术不变
// 生命周期由shared_ptr 管理,因此weak_ptr指向的对象可能为空
// 可使用lock 检查是否为空
// lock 返回一个指向共享对象的shared_ptr
if(shared_ptr<int> np = wp.lock())
{
.......
}
五、智能指针与动态数组
int *pia = new int[10]; // 10个未初始化的int
int *pia2 = new int[10](); //10个值初始化为0的int
string *psa = new string[10]; //10个空string
string *psa2 = new string[10](); // 10个空string
int * pia3 = new int[3]{0,1,2};
delete [] pia;
unique_ptr<int[]> up(new int[10]);
up.release(); //自动使用delete[] 销毁指针
// allocator 在头文件memory 中 // 将内存分配和对象构造分离 // 分配原始 未构造 // 是一个模板 allocator<string> alloc; //可以分配string的allocator 对象 auto const p = alloc.allocate(n); //分配n个未初始化的string
参考:
https://blog.csdn.net/k346k346/article/details/81478223
https://www.cnblogs.com/WindSun/p/11444429.html
《c++ primer》第12章
https://www.cnblogs.com/KunLunSu/p/7861330.html
本文标题为:C++(2)----智能指针与动态内存
基础教程推荐
- 带你深度走入C语言取整以及4种函数 2022-09-17
- C语言实现宾馆管理系统课程设计 2023-03-13
- C++实战之二进制数据处理与封装 2023-05-29
- 全面了解C语言 static 关键字 2023-03-26
- C语言 详解字符串基础 2023-03-27
- C++实现ETW进行进程变动监控详解 2023-05-15
- C语言编程C++旋转字符操作串示例详解 2022-11-20
- [C语言]二叉搜索树 2023-09-07
- [c语言-函数]不定量参数 2023-09-08
- centos 7 vscode cmake 编译c++工程 2023-09-17
