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的更多相关文章

  1. 编写高质量代码_改善C++程序的150个建议 读书笔记

    这几天看了下这本书<编写高质量代码_改善C++程序的150个建议>,觉的蛮有收获的,再次记录下自己以前不清晰的知识点,以供学习. 编写符合标准的main函数 C语言标准规定了main函数的 ...

  2. 改善c++程序的150个建议(读后总结)-------19-26

    19. 明白在c++中如何使用c c++可以兼容c的绝大部分代码,但是还是有一部分不能兼容. c语言的编译器在调用函数时会把函数翻译成 : "_函数名",例如: int nasa( ...

  3. 改善c++程序的150个建议(读后总结)-------12-18

    12.优先使用前置操作符 #include <iostream> using namespace std; class A { private: int num; public: A op ...

  4. 改善c++程序的150个建议(读后总结)-------0-9

    0. 不要让main 函数返回 void 入口函数main()返回类型应该为 int, 即程序结束时return 0 表示程序正常返回,函数结束时 return -1 值表示程序异常返回, 如果不显式 ...

  5. 改善c++程序的150个建议(读后总结)-------27-35

    27. 区分内存分配的方式 c++中内存分为5个不同的区 ①栈区 栈是一种特殊的数据结构,其存取数据特点为(先进后出,后进先出).栈区中主要用于存储一些函数的入口地址,函数调用时的实参值以及局部变量. ...

  6. 改善C++ 程序的150个建议学习之建议7:时刻提防内存溢出

    作为一个程序员,对内存溢出问题肯定不陌生,它已经是软件开发历史上存在了近40年的大难题.在内存空间中,当要表示的数据超出了计算机为该数据分配的空 间范围时,就产生了溢出,而溢出的多余数据则可以作为指令 ...

  7. 编写高质量代码改善C#程序的157个建议——建议150:使用匿名方法、Lambda表达式代替方法

    建议150:使用匿名方法.Lambda表达式代替方法 方法体如果过小(如小于3行),专门为此定义一个方法就会显得过于繁琐.比如: static void SampeMethod() { List< ...

  8. 改善java程序的151个建议

    <编写高质量代码-改善java程序的151个建议> --秦小波 第一章.开发中通用的方法和准则 1.不要在常量和变量中出现易混淆的字母 long a=0l; --> long a=0 ...

  9. 编写高质量代码改善java程序的151个建议——导航开篇

    2014-05-16 09:08 by Jeff Li 前言 系列文章:[传送门] 下个星期度过这几天的奋战,会抓紧java的进阶学习.听过一句话,大哥说过,你一个月前的代码去看下,慘不忍睹是吧.确实 ...

随机推荐

  1. Envoy 部署类型

    目录 Envoy 网络拓扑及请求流程 1. 术语 2. 网络拓扑 3. 配置 4. 更高层的架构 5. 请求流程 1. Listener TCP 接收 2. 侦听器过滤器链和网络过滤器链匹配 3.TL ...

  2. 一文读懂SuperEdge拓扑算法

    前言 SuperEdge service group 利用 application-grid-wrapper 实现拓扑感知,完成了同一个 nodeunit 内服务的闭环访问 在深入分析 applica ...

  3. 系统编程-网络-tcp客户端服务器编程模型(续)、连接断开、获取连接状态场景

    相关博文: 系统编程-网络-tcp客户端服务器编程模型.socket.htons.inet_ntop等各API详解.使用telnet测试基本服务器功能 接着该上篇博文,咱们继续,首先,为了内容的完整性 ...

  4. IntelliJ IDEA/Android Studio插件开发指南

    前言 目前在为安卓手机QQ做自动化的相关工作,包括UI自动化,逻辑层自动化等.使用到的uiautomator等框架,需要在Android Studio进行编码工作. 其中很多工作如果做到插件化的话,可 ...

  5. Day13_71_线程同步(synchronized)

    线程同步 * 异步编程模型和同步编程模拟的区别? - 有T1和T2 两个线程 > 异步编程模型:T1线程执行T1的,T2线程执行T2的,谁也不等谁 > 同步编程模型:T1和T2 线程执行, ...

  6. 2. robot framework 关键字,变量,循环

    1 关键字的使用 RF的能力是由关键字提供的,所以,我们必须对RF的常用关键字有个了解,这样才能把RF用好. 最常用的关键字就在RF的标准库中 http://robotframework.org 其中 ...

  7. 6- MySQL条件查询与通配符

    -数据库表中一般包含大量的数据,很少需要查询表中的所有行,通常只会根据特定的需要提取表中的一部分数据.这个时候需要制定查询条件,及过滤条件. -在select语句中,数据库根据where字句中指定的查 ...

  8. 【SpringBoot】Springboot2.x整合SpringSecurity

    一.Spring Security是什么?有什么作用(核心作用)?以及如何阅读本篇文章 1.是什么 Spring Security是Spring家族的一个强大的安全框架,与Springboot整合的比 ...

  9. dex文件格式学习

    一.dex文件的生成 我们可以通过java文件来生成一个简单的dex文件 编译过程: 首先编写java代码如下: (1) 编译成 java class 文件 执行命令 : javac Hello.ja ...

  10. 基于 RTF specification v1.7 的 RTF 文件解析及 OLE 对象提取(使用 Python 开发)

    0x01 Office RTF 文件介绍 RTF 文件也称富文本格式(Rich Text Format, 一般简称为 RTF),意为多文本格式是由微软公司开发的跨平台文档格式.大多数的文字处理软件都能 ...