【C++】Digest of 《effective C++》--2
2016-05-08 15:19
176 查看
《effective c++》阅读笔记02
条款01-视c++为一个语言联邦如今的c++是一个多重范型编程语言(multiparadigm programming language),同时支持过程形式(procedual)、面相对象形式(object-oriented)、函数形式(functional)、泛型形式(generic)、元编程形式(metaprogramming)。
四个关键词
C
c++是以c为基础的语言。blocks,statement,preprocessor,bulit-in types,arrays,pointers都来自c。
objective-oriented C++
体现c with classes。构造函数、析构函数、封装、继承、多态,virtual函数(动态绑定)……
tmplate C++
c++的泛型编程部分
STL
STL是一个template程序库。
由于c++继承自c,所以,当处理内置类型的数据时,用pass-by-value比价高效,而处理自定义类型的时候,往往用pass-by-reference-to比较好。
又由于STL的迭代器和函数对象都是在c指针的基础上塑造出来的,所以用pass-by-value又比较好。
c++高效编程守则视状况变化,取决于你使用c++的哪一部分。
条款02-尽量以const,enum,inline替换#define
#define所定义的记号是预处理器来处理的,所以在编译器编译之前,它就被预处理器移走了,因此,该记号没有进入记号表(symbol table)当我们定义如下:
#define ZERO 0
如果我们的程序出现编译错误时,这个错误信息会提到0而不是ZERO,因为这个记号是不在记号表里面的。而如果这个记号定义在一个非我们所写的头文件里,我们就会对这个莫名其妙的0没有概念,这将给团队合作的编程带来很大麻烦。
解决方法就是用常量代替上面的宏。即用const来定义一个常量表达式。
如:
const int zero = 0;
此时我们定义了一个语言常量,一定会进入记号表,所以会被编译器看到,这样出现错误信息的时候我们就比较容易理解。
当我们定义一个常量指针的时候要注意,要将指针而不只是指针所指之物声明为const,这时就要求我们写两次const
//example const char* const name = "name";
tips:在c++里,使用string比char*要合宜,所以可以写成如下:
const std::string name = "name";
其次,如果我们要定义一个class专属常量,是没办法使用宏做到。这时我们需要让它成为一个class的成员,而为了使之只有一个实体,必须把它定义为static成员。
class GamePlayer { private: static const int NumTurns = 5; //注意这只是一个声明式而非定义式 int scores[NumTurns]; };
通常情况下,c++要求我们对我们使用的任何一样东西提供定义式,但如果它是一个class专属常量又是static且为整数类型,只要不取它们的地址,我们可以只是声明而不必要提供定义式。
如果需要取该常量的地址,则需要另外提供定义式。
const int GamePlayer::NumTurns; //因为声明时已经给予初值,所以定义时不可以再设初值。
若旧式的编译器不支持在声明时给予初值,则将初值的赋予放在定义式中进行。
这时出现新问题,如果声明式里不能给予初值,则上面的scores数组就编译不通过,因为编译器坚持必须在编译期间知道数组的大小。
解决方法是用所谓的“the enum hack”补偿做法
基于原理:一个属于枚举类型(enumerated type)的数值可权充int被使用
class GamePlayer { private: enum{NumTurns = 5}; int scores[NumTurns]; //ok,成功编译 };
enum hack的行为某方面说比较像#define而不像const,如取一个enum的地址是不合法的。如果不想让别人获得一个pointers或reference指向我们的某个整数常量,就可以用enum实现。
像函数的宏有着很多缺点,尽量避免使用,可以用template inline函数来代替。
如我们可以将以下宏
#define CALL_WITH_MAX(a,b) f((a) > (b) ? (a) : (b)) //使用时会发现奇奇怪怪的错误
替换成
template<typename T> inline void callWithMax(cosnt T& a, const T& b) { f(a > b ? a : b); //不用担心出现奇奇怪怪的错误 }
而且使用inline函数可以实现封装,而宏是实现不了的。
对于单纯常量,最好以const对象或enums替换#define。
对于形似函数的宏(macros),最好改用inline函数替换#defines。
相关文章推荐
- Course Schedule II
- 异常规范和c++11
- 如何在VS2012 C++项目里面添加静态库文件lib
- C++第五次作业
- 【C/C++】printf 格式化输出
- C++制作俄罗斯方块
- C语言中const的用法
- C++第五次实验——数组分离
- 读《深度探索C++对象模型》之对象成员的效率
- C++第一次作业
- C语言关于数组与指针内容小结
- C++注释符问题
- 使用ctype.h示例
- c++/python
- 64. Minimum Path Sum 路径最小总和
- [C++]广度优先搜索(BFS)(附例题)
- 读《深度探索C++对象模型》之分层继承对于内存布局的影响
- 使用errno.h示例
- leetcodec_c++:Container With Most Water(011)
- C++实验5—数组分离