o2o网站,个人网页设计欣赏网站,一个ip上绑多个网站,广告类型有哪几种文章目录1. 内存对齐2. 递归中的内存对齐3. C引用的本质4. 致谢1. 内存对齐
通过以下语句#xff0c;获取变量的占用内存打下#xff1a;
cout size of int sizeof(int) endl;
cout size of int 引用的本质4. 致谢1. 内存对齐
通过以下语句获取变量的占用内存打下
cout size of int sizeof(int) endl;
cout size of int sizeof(int) endl;
cout size of char sizeof(char) endl;int 和 int 都占 4 字节 char 占 1 字节
编写一个类其包含1个 int2个 char排列顺序不同。
class memory1
{int id;char a;char b;
};
class memory2
{char a;int id;char b;
};
class memory3
{char a;char b;int id;
};可以看见他们的占用空间大小是不一样的。
size of memory1 8
size of memory2 12
size of memory3 8计算机从内存读取数据是按块读取的一般是4或者8的倍数一块一起读取CPU和内存IO的硬件限制导致没办法将一个数据类型分在两个块中读取内存对齐可以加快程序的运行速度一般编译器会在后台进行内存对齐优化但是也不能做到十分完美内存对齐的参数可以更改#pragma pack(n)n 1,2,4,8,16
所以上面的memory类的内存对齐是按照4字节进行的计算机按照顺序分配内存4字节剩余空间能放下某个类型的就放进去放不进去的新往下找一块4字节的空间放 int
加入#pragma pack(1)可见就是紧密排列了。
size of memory1 6
size of memory2 6
size of memory3 6#pragma pack(2)
size of memory1 6
size of memory2 8
size of memory3 62. 递归中的内存对齐
我在做LeetCode题的时候遇到一个递归爆栈问题
在这里做一些测试不保证结果具有通用性也请大家指正。
void dfs(int i) {int k 0;cout k k endl;cout i i endl;i i1;dfs(i);
}
int main() {int i 0;dfs(i);
}变更dfs(i)参数个数 递归次数32385第一个k的地址 0x61fdcck地址间隔 6410参数个数为1-4个 增加参数个数到5-6个 递归次数25908第一个k的地址 0x61fdbc比上面移动了16k地址间隔 8010 增加参数个数到7-8个 递归次数21589第一个k的地址 0x61fdac比上面移动了32k地址间隔 9610 增加参数个数到9-10个 递归次数18505第一个k的地址 0x61fd8c比上面移动了64k地址间隔 11210 增加参数个数到11个 递归次数16191第一个k的地址 0x61fd7c比上面移动了80k地址间隔 12810
增加参数个数到10个且全部改成引用 递归次数18505第一个k的地址 0x61fd8c比上面移动了64k地址间隔 11210 以上均为win1064位操作系统 环境 目前通过结果可以看见
参数的增多递归层数会减小递归中的栈也遵守内存对齐原则int 型的 对递归深度没有造成影响win10,64位
class memory1
{int id;char a[1280];char b;
};
int main() {int i 0;int j 0;int a 0, b 0, c 0,d0,e0,f0,g0,h0,l0;memory1 m1;dfs(m1,i, j, a, b,c,d,e,f,g,h);
}size of memory1 1288上面程序
递归次数1436第一个k的地址 0x61f34c比上面移动了2688k地址间隔 144010
将 m1 改成
cout size of memory1 sizeof(m1) endl;
size of memory1 8递归次数16181第一个k的地址 0x61f86c比上面移动了1376k地址间隔 12810
对于大型 结构数据采用能大幅节省空间递归不至于过早爆栈结束。
但是上面 LeetCode 爆栈就只是把 int改成int程序就不爆栈了跟认知的规律是不符合的还请大佬看看什么原因
3. C引用的本质
参考c中“引用”的底层实现原理详解 在读完上文后就清楚了引用会产生一个8字节的变量存储被引用的变量的地址所以上面win10的测试结果有点不可信可能这就是C在硬件、操作系统、编译器不同的情况下结果有差异的情况采用 linux 进行测试
在linux中测试结果
传入2个int 递归次数174522 传入2个int递归次数130885 传入2个double 递归次数130912 传入2个double递归次数104668
我想这个数值已经能够侧面说明上面链接文章中提到的引用本质了C引用的本质是指针但是它跟指针又不一样C对指针进行了封装产生了引用你在使用引用的时候传给你的是它里面指针所指向的内容。
所以对这种内置的变量类型函数调用的时候直接使用copy传入就可以了还比较省内存int 4字节使用 int 会占用 8字节
至此可以解释上面 LeetCode 那道题传入 int 爆栈了而改为 int 题目就AC通过了。
4. 致谢
感谢焦/huaix提出去掉可以解决问题开启了我对这个问题的思考 感谢Thin-k.调试确认是stack-overflow的问题 感谢CSDN群里的朋友热心讨论和研究还有论坛朋友akari10032的解答 感谢hitskyer和阿福的答疑 感谢所有在网络上分享知识的每一个博主
参考链接 带你深入理解内存对齐最底层原理 C/C内存对齐详解