改善c++程序的150个建议(读后总结)-------10-11
10. 优化结构体中元素的布局
结构体变量所占空间大小并不是其所含类型所占字节数之和,其所占内存字节数涉及到字节对齐。
字节对齐 :变量在内存中储存都是以字节数为单位,每一个字节都有自己的地址,逻辑上变量的首地址(第一个字节的地址)可以是任意位置,但实际不同类型变量其首地址是有一定规则的,这是为了更快的查找便于存取(牺牲空间来换取效率)。
结构体变量中的各个类型在内存中存放时也按照一定的规则,并不是简简单单的用连续的内存 挨边存放。
其遵循的规则有:
(1)结构体变量的首地址可以被其所含最宽的基本类型的大小所整除。
(2)其结构体变量所含各个基本类型的首地址相对于结构体变量的首地址来说的偏移量应为自身大小的整数倍。(如有需要,编译器会在两个基本类型存储的中间填充字节以满足要求)
(3)其结构体变量总的宽度应为其所包含的最宽基本类型大小的整数倍。(如有所需,编译器会在其尾部填充字节以满足要求)
在编程中可以利用上述规则来合理的安排定义数据的顺序减少占用的空间(即减少填充的字节)
,也可以自己显式的填充字节(其实显式填充和编译器自动填充一样,这些填充的内存单元都对程序每有意义)------------空间换取时间
在编程中如果对时间效率要求不高,而空间资源紧张的话可以利用编译器的pack()指令显式的调整结构体的对齐方式。
#pragma pack{ n } //n为字节数,其取值为1,2,4,8,16,默认是8
struct A
{
int a;
char b;
short c;
};
如果不用编译器的pack()指令的话则sizeof(A)为8.
如果利用pack()指令并让n为1的话,其结构体对齐方式为1字节对齐,则sizeof(A)为7
-----------时间换取空间
11. 尽量少用强制类型转换
c++保留了C风格的强制类型转换,而且具有自己新风格的强制转换
(1)c风格的强制类型转换
形式为:
类型标识符(待转换变量)或(类型标识符)待转换变量
这种强制类型转换比较危险,其会产生一些难以发现的问题,例如
int a=65536;
int i=unsigned short(a);
i的值为0;
因为在32位的机器中int型的数据占4个字节范围为-2147483648~2147483647
而unsigned short类型的数据占2个字节范围为
0~65535
当把一个大于65535的int类型数据强制转换为unsigned short类型数据时发生内存截断(4个字节截取后两个字节)。相同如果把unsigned类型的数据转换为int类型则会发生内存扩张。
(2)c++新式风格的强制类型转换
① const_cast<T*>(a)
其可以去除类中的const ,volatile,和__unaligned属性。
calss a
{
//code
};
int main()
{
const a *p1 =new a; //p1为一个指向常对象的指针变量
a *p2=p1; //错误,const指针不能赋值给非const指针
a *p3=const_cast<a*>(p1) //正确,
利用const_cast<T*>(a)对p1常指针进行强制类型转换去除其const属性,使其可以赋值给非const指针
②dynamic_cast<T*>(a)
其与c++的动态多态性有关。
c++中通过把基类函数设置为虚函数来实现动态多态性,即可以通过定义基类指针指向不同继承类对象来调用其相关方法,前提是这种继承类对象的相关方法得在基类中声明为虚函数,否则用基类指针无法直接调用。 这时候就需要获得这种继承类对象的类型,通过dynamic_cast<T*>(a)来强制转换其指针类型从而调用其特有方法
calss A
{
//code
};
class B:public A
{
//code
};
class C:public B
{
//code
};
int main()
{
A *p1=new C;
C *p2=dynamic_cast<C*>(p1); //正确,安全p2为C类型的指针
B *p3=dynamic_cast<B*>(p1); //错误,不安全p3为空指针
return 0;
}
通过p2指针就可以调用c类型特有的方法。
dynamic_cast<T*>(a)其是通过对类名称通过字符串比较来实现的,其在继承中所处的层次越深,其字符串比较的次数就越多(为了找到对应类名称),需要花费很大时间,不如不用直接定义对应类型的指针;
③reinterpret_cast<T*>(a)
它用于不同类类型指针之间的转换;
class A
{
.....
}
class B
{
......
}
int main()
{
A *p1=new A;
B *p2=reinterpret_cast<B*>(A);
return 0;
}
因为A与B是不同的两个类型,其具有不同的内存储存形式,强行对其转换可能会发生内存扩张或内存截断。
④static_cast<*T>(a)
**总结:**由上述可得在程序中使用强制类型转换会带来一系列安全问题,且不易发觉因此在程序中尽量少使用强制类型转换。
改善c++程序的150个建议(读后总结)-------10-11的更多相关文章
- 编写高质量代码_改善C++程序的150个建议 读书笔记
这几天看了下这本书<编写高质量代码_改善C++程序的150个建议>,觉的蛮有收获的,再次记录下自己以前不清晰的知识点,以供学习. 编写符合标准的main函数 C语言标准规定了main函数的 ...
- 改善c++程序的150个建议(读后总结)-------19-26
19. 明白在c++中如何使用c c++可以兼容c的绝大部分代码,但是还是有一部分不能兼容. c语言的编译器在调用函数时会把函数翻译成 : "_函数名",例如: int nasa( ...
- 改善c++程序的150个建议(读后总结)-------12-18
12.优先使用前置操作符 #include <iostream> using namespace std; class A { private: int num; public: A op ...
- 改善c++程序的150个建议(读后总结)-------0-9
0. 不要让main 函数返回 void 入口函数main()返回类型应该为 int, 即程序结束时return 0 表示程序正常返回,函数结束时 return -1 值表示程序异常返回, 如果不显式 ...
- 改善c++程序的150个建议(读后总结)-------27-35
27. 区分内存分配的方式 c++中内存分为5个不同的区 ①栈区 栈是一种特殊的数据结构,其存取数据特点为(先进后出,后进先出).栈区中主要用于存储一些函数的入口地址,函数调用时的实参值以及局部变量. ...
- 改善C++ 程序的150个建议学习之建议7:时刻提防内存溢出
作为一个程序员,对内存溢出问题肯定不陌生,它已经是软件开发历史上存在了近40年的大难题.在内存空间中,当要表示的数据超出了计算机为该数据分配的空 间范围时,就产生了溢出,而溢出的多余数据则可以作为指令 ...
- 编写高质量代码改善C#程序的157个建议——建议150:使用匿名方法、Lambda表达式代替方法
建议150:使用匿名方法.Lambda表达式代替方法 方法体如果过小(如小于3行),专门为此定义一个方法就会显得过于繁琐.比如: static void SampeMethod() { List< ...
- 改善java程序的151个建议
<编写高质量代码-改善java程序的151个建议> --秦小波 第一章.开发中通用的方法和准则 1.不要在常量和变量中出现易混淆的字母 long a=0l; --> long a=0 ...
- 编写高质量代码改善java程序的151个建议——导航开篇
2014-05-16 09:08 by Jeff Li 前言 系列文章:[传送门] 下个星期度过这几天的奋战,会抓紧java的进阶学习.听过一句话,大哥说过,你一个月前的代码去看下,慘不忍睹是吧.确实 ...
随机推荐
- 攻防世界 reverse BabyXor
BabyXor 2019_UNCTF 查壳 脱壳 dump 脱壳后 IDA静态分析 int main_0() { void *v0; // eax int v1; // ST5C_4 char ...
- pta 简单求和
6-1 简单求和 (10 分) 本题要求实现一个函数,求给定的N个整数的和. 函数接口定义: int Sum ( int List[], int N ); 其中给定整数存放在数组List[]中,正 ...
- Go语言GC实现原理及源码分析
转载请声明出处哦~,本篇文章发布于luozhiyun的博客:https://www.luozhiyun.com/archives/475 本文使用的 Go 的源码1.15.7 介绍 三色标记法 三色标 ...
- 运维干货|交换机不同VLAN之间及相同VLAN之内进行隔离
文中所展示的内容为VLAN与VLAN之间分隔关系,如相同VLAN用户之间进行分隔,相同VLAN一组用户之间允许通信并与其它一组用户之间进行分隔,属于VLAN的高级应用范畴.本文来源于智象运维某大神的日 ...
- 前端学习 node 快速入门 系列 —— 报名系统 - [express]
其他章节请看: 前端学习 node 快速入门 系列 报名系统 - [express] 最简单的报名系统: 只有两个页面 人员信息列表页:展示已报名的人员信息列表.里面有一个报名按钮,点击按钮则会跳转到 ...
- 为什么 Spring Boot 2.3.0 放弃Maven最终拥抱Gradle
在 2.3.0 中对 Spring Boot 进行了相当重大的更改,这是使用 Gradle 而非 Maven 构建的项目的第一个版本. Spring 的每个项目都独立的项目组在开发运营,在用户最常使用 ...
- Windows搭建Linux子系统(WSL)详细教程
介绍 WSL(windows下的Linux子系统) Windows Subsystem for Linux(简称WSL)是一个在Windows 10上能够运行原生Linux二进制可执行文件(ELF格式 ...
- 王炸!!IDEA 2021.1 推出语音、视频功能,边写代码边聊天,我真的服了…
IDEA 2020.3 刚没用多久,2021.1 又陆续给我推送更新了: 启动就提醒更新,麻烦,那不如更新下,体验下新版本. 如上图所示,2021.1 更新了 9 个新特性,下面栈长会一一体验给大家介 ...
- java POI(二)
name.xslx 1 public class Demo6 { 2 3 public static void main(String[] args) throws IOException { 4 I ...
- 由电脑专卖系统引发的Java设计模式:访问者模式
目录 定义 意图 解决问题 何时使用 优缺点 结构 电脑专卖系统 定义 访问者模式是对象的行为型模式,它的目的是封装一些施加于某些数据结构元素之上的操作,一旦这些操作需要修改的话,接收这个操作的数据结 ...