C++ 内存模型

2023-11-10

C++ 内存模型(未完。。。)

数据存储

  • 程序数据段
  • 程序代码段

stack栈内存

  • 栈内存属于执行期函数,编译时确定大小
  • 函数执行时栈空间自动分配,结束时栈空间自动销毁
  • 栈对象是线性分配,连续排列,没有内存碎片化效应
  • 栈内存具有函数本地性,不存再多线程竞争
  • 栈内存有大小限制,可能存在益处,linux默认未8MB,windows默认是1MB
  • 栈内存使用对象或引用直接使用,管理复杂度较低

heap堆内存

  • 堆内存具有全局共享特点,大小动态变化
  • 堆对象分为时手动分配(malloc/new),对象释放时,手动释放内存(delete/free)
  • 堆生对象链式分配,非连续排列
  • 堆内存全局共享,存在多线程竞争的可能性
  • 堆内存的大小没有栈内存严格限制,与机器内存总量和进程寻址空间有关
  • 对内存使用指针简介访问,管理复杂度较高

堆与栈

  • 栈内存分配快,内存连续,缓存友好,释放快
  • 生存中期短,拷贝少(传值、返回值),栈内存性能比堆内存性能好
  • 堆内存有更好的灵活性,但性能比栈内存差
  • 堆内存再长期运行的程序中有内存碎片化的效应,会造成小快内存无法使用(内存泄漏),降低缓存使用效率
  • 堆内存分配需要寻找合适内存大小的内存块,花费时间更多
  • 栈对像可以使用RAII和指针以动操作避免拷贝的代价

值语义和引用语义

  • 值语义:对象以值的方式直接存储,传值,返回值,拷贝等
  • 引用语义:对象已引用或指针的方式间接存储,穿传值,返回值,拷贝传递的是引用或指针
  • 值语义没有悬浮指针/引用,没有昂贵的释放操作,没有内存泄漏,没有数据竞争,但是值语义堆大对象拷贝代价高,不能支持虚函数多态

变量初始化

  • 使用统一初始化:int a{50}; int a2 = {50};
  • 赋值初始化:int a3 = 50;
  • 构造初始化:int a4(50);
  • 推荐使用统一初始化(列表初始化),可以避免隐式转换

指针容易出现的问题

  • 内存泄漏——忘记释放已经申请的内存
  • 悬浮指针——使用已经释放的内存,返回栈对象地址
  • 重复删除——对已经删除的对象进行二次删除
  • 删除非堆对象指针——对栈对像、全局/静态对象地址进行删除
  • 使用空指针/使用失效的引用
int* glob;
void process(int* q){
  glob = q; 
}
void g1(){
  int* p = new int{7};
  process(p);
  delete p;
  *glob = 9; //悬浮指针
}
void g2(){
  int* p = new int{7};
  process(p);
  delete p; 
  delete glob; //重复释放
}
void g3(){
  int x = 7;
  int* p = &x;
  process(p);
  delete glob;// 释放栈指针
}

对象内存空间

  • 虚函数占用一个指针的大小
  • 静态数据成员不参与类堆对象大小的计算
  • 初始化顺序按照成员变量声明顺序
  • 可以使用#pragma pack(4)来控制对象内存对齐的大小

特殊成员函数与三法则

  • 三法则:析构函数、拷贝构造函数、赋值操作符,三者自定义其一,则需要同时定义另外两个(否则编译器自动生成的一般语义有误)
  • 使用default让编译器自动生成;使用delete让编译器不要自动生成;
  • 编译器自动生成的的拷贝/赋值时按字节拷贝,若出现指针等具有动态数据成员的对象,通常需要自己定义拷贝/赋值/构造行为
  • 赋值操作符中的copy和swap是较为好的方法(注意赋值操作中需要避免自我赋值的情况)
  • 普通类的成员函数其实相当远一个带有this指针的全局函数。静态成员函数其实不属于类,是一个全局函数,没有this指针;

性能指南

  • 如果函数非常小,且时间很敏感,可已将其声明未inline
  • 如果函数可能在编译器进行求值,将其声明为constexpr
  • 尽量使用类初始化列表对类成员变量进行初始化
  • explicit 避免隐式转换
  • 使用重载避免引述转换
  • 返回值优化(RVO)

vector 与 array

  • vector在堆上,array在栈上
  • vector使用时,建议设置大小,reserve(1000),避免vector的内存增长带来的拷贝
class MyClass {
public:
	MyClass() = default;//强制生成默认的构造函数
	~MyClass() = delete;//强制删除改构造函数
	MyClass(const MyClass& tmp) = delete;
	MyClass(const MyClass&& tmp) = delete;//移动拷贝
	MyClass& operator=(const MyClass& tmp) = delete;
	MyClass& operator=(const MyClass&& tmp) = delete;//移动赋值
};
class Point
{
public:
	Point(int x, int y) : x_(x), y_(y) {}
	int x_;
	int y_;
};
class Rectangle
{
public:
	Point* left_up_;
	int length_;
	int width_;
	//禁止构造函数隐式转换
	explicit Rectangle(int date) {}
	Rectangle(int x, int y, int length, int width) : left_up_(new Point(x,y)), length_(length), width_(width) {}
	Rectangle(const Rectangle& rect) : length_(rect.length_), width_(rect.width_)
	{
		if (rect.left_up_ != nullptr)
			left_up_ = new Point(*rect.left_up_);
		else
			left_up_ = nullptr;
	}

	Rectangle& operator=(const Rectangle& rect)
	{
		if (this == &rect)
			return *this;
		Rectangle temp(rect);
		swap(left_up_, temp.left_up_);
		this->length_ = temp.length_;
		this->width_ = temp.width_;

		return *this;
	}

	~Rectangle()
	{
		delete left_up_;
		left_up_ = nullptr;
	}
	
	inline friend ostream& operator<<(ostream& os, const Rectangle& rect);
};

ostream& operator<<(ostream& os, const Rectangle& rect)
{
	return os << "{" << rect.left_up_->x_ << "," << rect.left_up_->y_ << "," << rect.length_ << "," << rect.width_ << "}" << endl;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++ 内存模型 的相关文章

  • 采用 std::vector 或 std::array 的模板函数

    我有一个函数 当前接受 2 个向量 其中可以包含任何普通的旧数据 template
  • 如何通过覆盖 MSBuild 目标来防止外语资源生成?

    我正在致力于减少大型 C ASP NET 解决方案的编译时间 我们的解决方案使用通常的 resx 文件方法翻译成大约十几种外语 这些资源文件的解析和编译极大地减慢了我们的编译时间 并且是日常的挫败感 我知道可以创建自定义资源提供程序并摆脱
  • C# 中类似图的实现

    所以我有一个对象 我们称之为 Head 它有一个对象列表 C C1 C2 C3 T T1 T2 和 M M1 M2 并且所有这些都是相互关联的 例如 Head gt C1 C2 C3 T1 T2 M1 M2 T1 gt C1 C2 T2 g
  • Linux命令列出所有可用命令和别名

    是否有一个 Linux 命令可以列出该终端会话的所有可用命令和别名 就好像您输入 a 并按下 Tab 键一样 但针对的是字母表中的每个字母 或者运行 别名 但也返回命令 为什么 我想运行以下命令并查看命令是否可用 ListAllComman
  • 如何通过 libwebsocket 发送异步数据?

    我正在将 Warmcat 的 libwebsocket C 库用于小型 Websocket 服务器 我已经启动并运行了这些示例 并且可以发送数据以响应从 websocket 接收数据 例如回显发送的反向字节 但是 我无法弄清楚如何在不使用
  • 我可以将 char 或 DateTime 设置为 null 吗?

    我可以将 null 设置为char数据类型 并且DateTime在 C 中 多谢你们 这是不可能的 它是一个值类型 使用 char myChar null DateTime myDate null 这相当于 Nullable
  • 从内存流播放视频文件

    只是好奇看看这是否可能 我有一个 Windows 应用程序 它从我的电脑上的 avi 文件读取所有字节 然后将其存储在 byte 中 现在我的内存中有 avi 文件 我想直接从内存将其加载到某种视频播放器控件中 我尝试过使用 wmplaye
  • 如何使用 CUDA/Thrust 对两个数组/向量根据其中一个数组中的值进行排序

    这是一个关于编程的概念问题 总而言之 我有两个数组 向量 我需要对一个数组 向量进行排序 并将更改传播到另一个数组 向量中 这样 如果我对 arrayOne 进行排序 则对于排序中的每个交换 arrayTwo 也会发生同样的情况 现在 我知
  • 如何在 Visual Basic DLL 和 C++ DLL 之间创建隔离/免注册 COM?

    我必须在 C DLL 中使用 VB COM DLL 我弄清楚了如何从 C DLL 访问 VB COM DLL 并且它可以工作 现在我遇到了一个问题 我必须使用隔离的 COM 免注册 COM 因为我无法在必须使用它的每台 PC 上注册 DLL
  • 为什么 BinaryFormatter 可以序列化 Action<> 但 Json.net 不能

    尝试序列化 反序列化 Action 尝试我的 1天真 JsonConvert SerializeObject myAction JsonConvert Deserialize
  • FluentAssertions ShouldNotThrow 无法识别异步方法/Func

    我正在尝试检查异步方法是否抛出具体异常 为此 我使用 MSTEST 和 FluentAssertions 2 0 1 我已经检查过这个关于 Codeplex 的讨论 http fluentassertions codeplex com wo
  • 原子存储抛出错误

    我最近升级到了 C 11 兼容编译器 并且尝试将一些代码从 boost 更新到 c 11 标准 我在使用atomic store转换一些代码时遇到了问题 这是一些简单的测试代码 似乎会引发编译器错误 int main std shared
  • 模板与非模板类,跨编译器的不同行为

    我在一些应用程序中使用编译时计数器 它确实很有用 昨天我想用 gcc 编译一个程序 我之前使用的是 msvc 并且计数器的行为在模板类中发生了变化 它在模板类中不再工作 过于简化的代码 Maximum value the counter c
  • 节点*链表中的下一个

    我是数据结构和算法的新手 我遇到了以下代码 typedef struct node int data node next 谁能告诉我为什么我们要声明节点 next next 不能声明为 int next 吗 因为你希望能够做到n gt ne
  • 冒号在c中起什么作用?

    我在课堂上得到了这个例子 但我不确定它的作用 我知道冒号添加了一个位字段 但我仍然不确定这个问题 a b gt 0 3 1 运算符称为条件运算符 If b值为 gt 0 价值3被分配给a否则值1被分配给a 以 Kernighan Ritch
  • 如何禁用基于 ValidationRule 类的按钮?

    如何禁用基于 ValidationRule 类的 WPF 按钮 下面的代码可以很好地突出显示 TextBox
  • 使用 cmake 将两种解决方案合二为一

    我有两个单独的 Visual Studio 2013 解决方案 我想将它们迁移到一个解决方案中 因为第一个解决方案 使用 Qt 充当第二个解决方案的 GUI 最后 我希望有一个结构如下的单一解决方案 Solution All Build P
  • 在特定线程上运行工作

    我想要一个特定的线程 任务队列并在该单独的线程中处理任务 应用程序将根据用户的使用情况创建任务并将其排队到任务队列中 然后单独的线程处理任务 即使队列为空 保持线程活动并使用它来处理排队任务也至关重要 我尝试过几种实现TaskSchedul
  • 为什么 C++ 标准没有将 sizeof(bool) 定义为 1?

    Size of char signed char and unsigned char由 C 标准本身定义为 1 个字节 我想知道为什么它没有定义sizeof bool also C 03 标准 5 3 3 1 说 sizeof char s
  • Asp.Net Core 中的 SSL 不起作用

    我从 Visual Studio 创建了一个简单的 Web 应用程序Web Application Net Core 具有个人用户帐户授权的模板 然后 我启用了 SSLProject gt MyProject Properties 将带有

随机推荐

  • 【C++学习第十一讲】C++数据类型

    文章目录 一 编程语言中的数据类型 1 1 整型 Integer 1 2 浮点型 Floating Point 1 3 字符型 Character 1 4 布尔型 Boolean 1 5 数组 Array 1 6 字符串 String 1
  • alter database open oracle,alter database open resetlogs

    关于alter database open resetlogs及incarnation的一点理解 不完全恢复只能做一次吗 采用rman的默认设置 对数据库进行了backup database备份 进行了一些操作后 然后直接关闭启动到moun
  • JS下载网页为PDF

    1 准备引入包
  • FinalShell连接VM出现channel is not opened.

    问题描述 用finalshell连接虚拟机的服务器时显示连接成功 之后马上出现channel is not opened 解决方案 打开虚拟机 找到相关配置文件 cd etc ssh 更改配置 vi sshd config 找到被注释的 U
  • linux下SD卡mount的问题

    最近发现嵌入式开发板上 有的SD卡 8G SDHC 可以mount 有的则失败 2G SD 仔细看log信息 发现有如下区别 mount成功时 mmc0 host does not support reading read only swi
  • 【JavaScript】利用JS实现柱形统计图

    CSS代码部分
  • 嵌入式(信号机制)

    信号机制 概念 信号是在软件层次上对中断机制的一种模拟 是一种异步通信方式 所有信号的产生及处理全部都是由内核完成的 信号的产生 1 按键产生 2 系统调用函数产生 比如raise kill 3 硬件异常 4 命令行产生 kill 5 软件
  • 拟合工具箱的几个误差参数说明

    使用过Matlab的拟合 优化和统计等工具箱的网友 会经常遇到下面几个名词 SSE 和方差 误差平方和 The sum of squares due to errorMSE 均方差 方差 Mean squared errorRMSE 均方根
  • IDEA打开启动Vue项目和Vue文件

    一般前端Vue都是用VsCode专门用来编辑 今天突发奇想想用IDEA去编辑 首先把项目从git下拉下来在IDEA中打开 在IDEA打开终端运行相关命令 打开终端 也可以通过alt F12快捷键 终端如下 自行根据需要输入命令即可 相关代码
  • SMB、FTP、DNS、等六个服务总结

    一 SMB服务 1 SMB服务功能 不同系统主机之间实现文件 打印机等资源共享 2 SMB服务主配置文件路径 etc samba smb conf 3 SMB服务启动 重启 停止 方法 service smb start restart s
  • 如何使用docker和docker-compose在本地Testnet上开发EOS区块链

    EOS区块链的开发并不是立竿见影的 因为需要一些非显而易见的组件 需要对它们进行配置和协同工作 nodeos 块生成器守护程序 keosd 钱包守护进程 存储私钥 eosio cpp 智能合约编译器 eosio token 平台的参考标记
  • chapter1 静态分析技术-08PE文件分析 PEview

    1 下载PEview peview exe下载 peview exe绿色版 peview exev0 9 8 0绿色中文版 华军软件园https www onlinedown net soft 977166 htm 2 解压后打开PEvie
  • OTL、OCL、BTL电路及其判断方法(转)

    OTL OCL BTL电路及其判断方法 OTL Output Transformer Less 电路 称为无输出变压器功放电路 是一种输出级与扬声器之间采用电容耦合而无输出变压器的功放电路 它是高保真功率放大器的基本电路之一 但输出端的耦合
  • 鱼和熊掌不可兼得:Spring boot3,Swagger3(使用Mybatis-Plus搭建框架)

    文章写于2023年7月1日 目前使用的配置尽量用最新的 如果晚于这个日期很久 请参考新的配置 使用MyBatis plus搭建框架后使用swagger或者采用的Spring 3后使用swagger 3 启动项目出现如下错误 Type jav
  • 计算机视觉(二):图像检索以及基于图像描述符的搜索

    1 引言 在图像识别中 我们通常将图片的特征提取出来 并使用这些主要特征来进行识别 在OpenCV中提供了许多特征检测算法 下面让我们来学习一下怎么使用这些算法 2 特征定义 粗略的讲 特征就是有意义的图像区域 该区域具有独特性或易于识别性
  • C++14 新特性

    一 新的语言特性 1 泛型的 Lambda 函数 在 C 11 中 lambda 函数的形式参数需要被声明为具体的类型 C 14 放宽了这一要求 允许 lambda 函数的形式参数声明中使用类型说明符 auto auto lambda au
  • Alist V3版本 API使用文档 -个人整理

    Alist V3 API 整理 Alist V3是一个支持多种存储 支持网页浏览和 WebDAV 的文件列表程序 由 gin 和 Solidjs 驱动 Alist的官方文档提供了V2版本的API说明 但对于最新的V3版本并没有 这里个人整理
  • 主析取范式与主合取范式原理探究

    主析取范式 对任意一个命题公式来说 主析取范式与主合取范式都是唯一的 命题变元指原子化的 P Q命题 极小项的定义 包含全部N个命题变元的合取式 称其为极小项 且N个命题变元中 每个变元与它的否定不能同时存在 但两者中必有一个出现且仅出现一
  • 怎样加入马云,马化腾,李彦宏的微信

    让马化腾出如今你的微信聊天里面 首先声明不是 PS 我不会 PS 的 这是程序截图 例如以下图 程序源码 http git oschina net LittleDY isWeiXin 我在他的基础上 又一次设计了图片和聊天记录 图片来自百度
  • C++ 内存模型

    C 内存模型 未完 数据存储 程序数据段 程序代码段 stack栈内存 栈内存属于执行期函数 编译时确定大小 函数执行时栈空间自动分配 结束时栈空间自动销毁 栈对象是线性分配 连续排列 没有内存碎片化效应 栈内存具有函数本地性 不存再多线程