IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> c++ primer/第十二章 动态内存 -> 正文阅读

[C++知识库]c++ primer/第十二章 动态内存

1.内存分区

一般分为五个区

五个区存放
保存定义在函数内的非static对象,const 修饰的局部变量[声明周期结束由编译器自动销毁]
存储动态分配对象(new,malloc)[需要手动释放]
全局/静态存储区保存局部static对象,类static对象以及定义在任何函数之外的对象(全局) [程序结束编译器自动销毁]
常量存储区存放常量字符串,const 修饰的全局变量.
代码区存放函数体(类的成员函数、全局函数)的二进制代码;
int a = 0;
const int b = 0;

const char* c = "hello";
const char* d = "hello";

static int e = 0;
const static int f = 0;

cout << &a << endl;		//010FF96C			
cout << &b << endl;		//010FF960			//说明静态局部变量存储在栈中
cout << &c << endl;		//010FF954			//这是个误区,这样输出其实是输出指针的地址,指针存放在栈中
cout << static_cast<const void *>(c)<< endl;	//00612B3C		//这样才是输出字符串存放的地址
cout << static_cast<const void *>(d)<< endl;	//00612B3C		//说明指向同一个常量字符串的指针地址相同
cout << &e << endl;		//006192E4		
cout << &f << endl;		//00612B30		//说明const修饰的全局(静态)变量也是放在常量存储区

注意:

  • 指针本身存在调用栈中,指针指的数据在堆中。
  • 指向同一个常量字符串的指针地址相同

2.智能指针

1. shared_ptr

允许多个指针指向同一个对象,内部有一个引用计数.当引用指针为0时,会调用对象的析构函数释放空间

  • 递增
    • 当作为一个shared_ptr初始化另外一个shared_ptr
    • 作为参数传递给一个函数以及作为函数的返回值
  • 递减
    • 给一个shared_ptr附上一个新值
    • shared_ptr被销毁
    • 局部的shared_ptr离开作用域
//智能指针均为模板类
//使用*之前一定要初始化后,而且初始化值不能为空
shared_ptr<int> sptr/shared_ptr<int> sptr(nullptr);;
*sptr = 1;			//不可以,这时候sptr为nullptr,不能进行解引用 
cout << *sptr;

int a = 0;
shared_ptr<int> sptr(new int(a));
*sptr = 1;		//可行,因为sptr已经不为空了,解引用不会报错
cout << *sptr;

//如果是自带初始化的,就可以直接用*解引用
shared_ptr<string> sptr;
if (sptr && sptr->empty())
    *sptr = "hello";

//技术
智能指针 = 另一个智能指针 //左边计数-1,右边计数+1

2.函数

//1.make_shared:最安全的分配和使用动态内存的,可以用类型的构造函数
shared_ptr<int> sptr = make_shared<int>(42);
cout << *sptr << endl;
//也可以用auto
auto sptr = make_shared<int>(42);
cout << *sptr << endl;

//初始化和函数
shared_ptr<T> p(q)			//p管理内置指针q的对象,q必须是new分配的内存.且能转为T*型;
shared_ptr<T> p(u)			//p从unique_ptr那里抢过来对象的所有权,将u置空
shared_ptr<T> p(q,d)		//p接管了内置指针q所指向的对象的所有权.q必须能转为T*型.p将使用可调用对象d来代替delete;
shared_ptr<T> p(p2,d)		//p是p2的拷贝,区别在于p可调用对象d来代替delete
 
p.get();					//返回一个内置指针,指向智能指针管理对象.!少用!;如果被清理,智能指针也会变空悬指针
    
p.reset();					//reset释放p
p.reset(q);					//调用delete,释放完后指向q
p.reset(q,d);				//调用d释放p,再指向d

3.生存周期

  • 可以把他当初一个局部变量
  • 只有一种情况会不会释放,就是把指针放在容器中,但是结束的时候没有把他删除掉;用完记得erase()

2. unique_ptr

只允许当前指针独占对象,当unique_ptr被销毁,那么指向的对象也会被销毁

  • 没有make_shared函数类型的函数,只能通过new来完成绑定
  • 不支持普通的拷贝或者赋值
//直接初始化
unique_ptr<int> p2(new int(42));		//正确,直接初始化


//初始化和函数
unique_ptr<T> 	u1			//空指针,可以指向T*的对象
unique_ptr<T,D> u2			//u2可以调用D来释放它的对象
unique_ptr<T.D> u(d)		//空unique,指向类型为T*的对象,用类型为D的对象d代替delete
    
u = nullptr;				//直接释放对象,变为空指针
u.release();				//u放弃对指针的控制权,返回指针,将u置空, 指针被返回,可用于转移.
							//如果不是赋值智能指针,那么记得释放内存
    
p.reset();					//reset释放p
p.reset(nullptr);			//释放p,置空
p.reset(q);					//调用delete,释放完后指向q,可用于转移

传递和返回unique_ptr

//返回即将被销毁的智能指针
unique_ptr<int> clone(int p)
{
	return unique_ptr<int>(new int(p));		//正确
}

//返回局部对象智能指针
unique_ptr<int> clone(int p)
{
    unique_ptr<int> ret(new int(p))			//正确
	return ret;
}

3. weak_ptr

是一种软引用,可以指向shared_ptr 的对象

3. new 关键字

string *ps1 = new string;		//默认初始化为空
string *ps2 = new string();		//初始化为空
int *pi1 = new int;				//默认初始化,*pi1的值未定义
int *pi2 = new int();			//初始化为0

//正常情况下,new失败就会抛出异常 bad_alloc,但是可以让他不抛出,返回null
int *p2 = new (nothrow)int;		//阻止抛出异常

4. delete 关键字

int i = 0;
int *pi1 = &i;
int *pi2 = nullptr;

double *pd = new double(33);
double *pd2 = pd;

delete pi1;			//编译通过,运行错误,pi1指向一个局部变量
delete pi2;			//正确,空指针可以delete


delete pd;			//正确,释放内存
delete pd2;			//编译通过,运行错误,未定义,内存以及被释放

//指针释放

空悬指针

double *pd = new double(33);
delete pd;			//正确,指针被释放后,会变成空悬指针,即有指向地址,但是地址已经被释放,无效了.再次delete就是未定义操作
pd = nullptr;		//如果还需要用,那么就指定为空;

//指向同一内容的指针
double *pd = new double(33);
auto pd2 = pd;
delete pd;		//pd2也会变为空悬指针
pd = nullptr;	//pd2为空指针,但是pd2仍未空悬指针
delete pd2;    	//报错

5. new 和 智能指针搭配

//可以让智能指针指向一块内存,但是想初始化必须是直接初始化
shared_ptr<int> p1 = new int(1024);		//错误,必须使用直接初始化形式.因为无法从内置指针转化为智能指针
shared_ptr<int> p2(new int(42));		//正确,直接初始化

不要混合使用内置和智能

void process(shared_ptr<int> ptr){...}


int *x(new int(1024));
process(x);		//错误,无法从内置指针转化为智能指针
process(shared_ptr<int>(x));		//正确,但是x的内容会被清除,变为空悬指针
*x;				//未定义
  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-03-08 22:10:02  更:2022-03-08 22:11:19 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 4:48:57-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码