《高质量C++编程》笔记一

本文深入探讨了C++编程中的封装、继承、抽象、空类型、大端模式、类型转换、多维数组、符号常量、栈与堆、函数参数传递、返回值策略、作用域规则、指针与引用、全局变量管理、类成员函数类型、联合类型、赋值操作、内存安全、C++特性应用等核心概念与实际应用,旨在帮助开发者掌握C++编程的精髓与最佳实践。

//2012-09-26 by llh

 

         把共性的部分提取出来,也就是抽象,组成一个类,就是封装,以后使用的时候重用,就是继承。共性越通用,类越抽象。比如数据库的记录维护功能(增删改等),就可以作为一个类来写,以后使用时给某些属性赋值进行操作。

 

           Void标示空类型,这种类型的大小无法确定,void指针可以作为通用指针,可以指向任何类型的对象,常用于函数参数中传递一个函数与其调用者之间约定好的类型的对象地址。

 

        大端模式,高地址在前,低地址在后,高字节存在高地址,从上向下读。

        Intel小端模式,高字节存在低地址,从下向上读。

 

        大端模式要求自然对齐,就是基本数据类型的对象不能简单存储于内存中的任意位置处,其起始地址必须能够被他们的大小整除。如int变量地址应该被4整除,short应该是偶数。

 

        在对不同的数据类型进行操作时,编译器(隐式转换)通常数据类型转换,或用户(强制类型转换),类型转换并不改变原来的类型和值,而是生成了新的临时变元,类型为目标类型。

 

        类型转换所带来的安全性包括,内存访问范围的扩张,内存的截断(内存访问的安全性),尾数的截断,值得改变和溢出(数据的安全性)。

 

        可以直接将派生类对象转换为基类对象:派生类对象必须保证期基类子对象的完整性,即其中基类子对象的内存映像必须和真正的基类对象的内存映像一致。但不可以把基类的对象直接转换为派生类对象,因为可能导致基类可访问范围扩张。

 

       对C++多维数组来说,先行后列的便利效率更好。

 

        存在两种符号常量,用#define定义的宏常量和const定义的常量。尽量使用含义直观的符号常量来标示在程序中多次出现的数字或字符串。Const常量具有数据类型,方便编译器的检查,另外#define宏替换可能出现边际效应。Const不仅应用于定义符号常量,任何需要预防意外修改数据的地方,均使用const。如const数据成员,const成员函数,const返回类型,const参数。

 

        Const可以放在类中声明常量,但是每个类均有自己的常量,且有生存期的限制,引入static const.或通过类中的枚举enum来实现。枚举常量不会占用对象的存储空间,编译时已经求值。

 

        栈(堆栈)和自由存储空间(堆)的主要区别是堆栈是自动管理的,局部变量的创建和销毁,堆栈的释放都是有函数自动完成,函数堆栈在预先分配好的空间创建,对比动态内存分配,更快更安全。

 

        堆栈的3个用途:进入堆栈前保存环境变量和返回地址,进入函数时保存实参的拷贝,函数体内保存局部变量。

 

        C++中函数参数和返回值的传递三种方式,传值,传指针,传引用。入参可以在类型前加const,防止该指针指向内存单元在函数体内无意中被修改。如果输入参数以值传递方式传递对象,宜改用”const &” 方式来传递,因为引用的创建和销毁不会调用对象的构造和析构函数,从而提高效率。

 

        将正常值用输出参数获得,错误标志return返回。有时候函数原本不需要返回值,但为了增加灵活性和支持链式表达式,可以附加返回值。

 

       一个函数应该在其入口处对参数的有效性进行检查,在函数体的出口处,对return 语句的正确性和效率进行检查。

 

        Return语句不可返回指向堆栈内存的指针或者引用”,因为该内存单元在函数体结束时被自动释放。弄清返回的究竟是对象的值,对象的指针,还是对象的引用。如果函数返回值是一个对象,要考虑return语句的效率。

 

        创建临时对象并返回的效率高于创建一个局部对象并返回它的结果。减少了一个对象的拷贝和开销的过程,提高效率。即return String(s1 + s2)优于 string result(s1 + s2), return result;

 

        尽量避免函数带有记忆功能。

 

        常量变量和函数具有四种存储类型,extern, auto, static, register.四种存储类型可分为两种生存期限,永久的(externstatic)和临时的(autoregister)。

 

        全局变量和全局函数的存储类型是extern,显示的声明static的全局变量和全局函数具有static存储类型,只能被同一个编译单元的函数调用。

 

         全局常量的默认存储类型是static,除非在定义了它的编译单元之外的其他编译单元中显式地用extern声明,否则不能被访问。

 

         一个标示符能够起作用的程序范围称为作用域,其中包括程序块,函数,文件,还包括C++中的类和命名空间。在函数内部可以使用域解析运算符::来引用全局变量。

 

        可以使用if( NULL != p)作为assert判断。

 

        Const可以防止意外改动指针指向的内存单元,起到保护的作用。

        Void StringCopy(char *strDest, const char *strSrc);

 

         对ADT/UDT的参数而言,void Func(A a)这样的声明的函数注定效率低下,可以将函数声明改为 voidFuncA &a),因为引用传递仅借用一下参数的别名而已,不需要产生临时对象,为防止引用传递时改变参数a,函数最终声明为void Func(const A & a);

即将ADT/UDT的值传递改为const引用传递。

 

        全局指针变量默认初始值是NULL non-static局部指针变量p,必须显式的指定其初值,第一次使用指针时应该用if( NULL ==p)来检查p的有效性,

 

       数组名本身是一个指针常量,即 a等价于int * const a,因此不能试图修改数组名的值,数组名的值就是数组第一个元素内存单元的首地址。即a = &a[0].如果想把b的内容指派给a,必须按照逐个元素赋值,或者使用内存拷贝。

 

        类的成员函数有四种类型,inline, virtual, static, normal, inline函数。

       类的静态成员函数不依赖与类的对象而存在,也不依赖与类的对象而调用,因此和普通全局函数没什么区别。只是作用域变成了类作用域。

 

         引用在创建时必须初始化,即引用到一个有效的对象,创建之后不可改变,引用的创建和销毁不会调用类的构造函数和析构函数,引用既具有指针的效率,又体现了最小特权原则。指针在定义时不必初始化,且指针可以初始化为NULL,创建之后可以改变。

 

         C++支持相同类型对象之间的直接赋值操作,默认的operator=语义。对象按成员拷贝语义,但是不能直接比较大小和判等。相同类型的对象各数据成员在内存中的布局是一致的。

 

         联合作为一种构造数据类型,提供了一种使不同类型数据成员之间共享存储空间的方法。同时可以实现不同类型数据成员之间的自动类型转换。联合的内存大小取决于其中字节数最多的成员,联合中存储的数据值完全取决于对它的解释方式。

 

         使用函数指针注册一个回调函数,函数名就代表函数的首地址,可以直接把函数名直接指派给同一类型的函数指针而不需要使用&运算符。

目 录 前 言6 第1 章 文件结构 1.1 版权和版本的声明. 1.2 头文件的结构. 1.3 定义文件的结构. 1.4 头文件的作用. 1.5 目录结构. 第2 章 程序的版式 2.1 空行. 2.2 代码行. 2.3 代码行内的空格. 2.4 对齐. 2.5 长行拆分. 2.6 修饰符的位置. 2.7 注释. 2.8 类的版式. 第3 章 命名规则 3.1 共性规则. 3.2 简单的WINDOWS 应用程序命名规则. 3.3 简单的UNIX 应用程序命名规则 第4 章 表达式和基本语句 4.1 运算符的优先级. 4.2 复合表达式. 4.3 IF 语句 4.4 循环语句的效率. 4.5 FOR 语句的循环控制变量. 4.6 SWITCH 语句. 4.7 GOTO 语句. 第5 章 常量 5.1 为什么需要常量. 5.2 CONST 与 #DEFINE 的比较. 5.3 常量定义规则. 5.4 类中的常量. 第6 章 函数设计 高质量C++/C 编程指南,v 1.0 2001 Page 4 of 101 6.1 参数的规则. 6.2 返回值的规则. 6.3 函数内部实现的规则. 6.4 其它建议. 6.5 使用断言. 6.6 引用与指针的比较. 第7 章 内存管理 7.1 内存分配方式 7.2 常见的内存错误及其对策 7.3 指针与数组的对比 7.4 指针参数是如何传递内存的? 7.5 FREE 和DELETE 把指针怎么啦? 7.6 动态内存会被自动释放吗?. 7.7 杜绝“野指针”. 7.8 有了MALLOC/FREE 为什么还要NEW/DELETE ?. 7.9 内存耗尽怎么办?. 7.10 MALLOC/FREE 的使用要点 7.11 NEW/DELETE 的使用要点. 7.12 些心得体会 第8 章 C++函数的高级特性 8.1 函数重载的概念. 8.2 成员函数的重载、覆盖与隐藏. 8.3 参数的缺省值. 8.4 运算符重载. 8.5 函数内联. 8.6 些心得体会. 第9 章 类的构造函数、析构函数与赋值函数 9.1 构造函数与析构函数的起源. 9.2 构造函数的初始化表. 9.3 构造和析构的次序. 9.4 示例:类STRING 的构造函数与析构函数 9.5 不要轻视拷贝构造函数与赋值函数. 9.6 示例:类STRING 的拷贝构造函数与赋值函数 9.7 偷懒的办法处理拷贝构造函数与赋值函数. 9.8 如何在派生类中实现类的基本函数. 9.9 些心得体会. 第10 章 类的继承与组合. 高质量C++/C 编程指南,v 1.0 2001 Page 5 of 101 10.1 继承 10.2 组合 第11 章 其它编程经验. 11.1 使用CONST 提高函数的健壮性 11.2 提高程序的效率 11.3 些有益的建议 参考文献 附录A :C++/C 代码审查表. 附录B :C++/C 试题. 附录C :C++/C 试题的答案与评分标准.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值