Effective C++学习笔记(一)const、enum、inline、const_cast、初始化对象

Effective C++学习笔记(一)

条款01:视C++为一个语言联邦
c++可以看成是由四个次语言组成的即:C、Object-Oriented C++、Template C++、STL。
对于内置类型而言,pass-by-value通常比pass-by-reference更加高效,但对于用户定义的类,由于构造函数和析构函数的存在,pass-by-reference-to-const 往往更好
条款02:尽量以const、enum、inline替换#define
使用常量替换宏,宏定义在被编译器看到之前可能就被预处理器处理掉了。常量会被放到记号表内。
static成员只有一份实体

class gameplayer
{
	static const int NumTurns = 5; //常量声明式  注意这里满足 static、整数类型(int char bool)
	int scores[NumTurns]; //使用该常量
}

也可以这样:

class gameplayer
{
	enum{ NumTurns = 5}; //令NumTurns成为5的一个记号名称
	int scores[NumTurns]; //使用该常量
}

对于其他类型的:

class gameplayer
{
	static const double NumTurns ;  
}
const double gameplayer::NumTurns = 1.35;

使用宏定义函数可能由于反复的替换导致意想不到的结果。
总结:1.对于单纯常量,最好以const对象或enums替换#define
2.对于形似函数的宏,最好改用inline内联函数替换
条款03 尽可能使用const
const会执行一个语义约束,即指定一个不被改动的对象
注意const如果出现在星号的左边 表示被指物是常量,出现在星号的右边表示指针自身是常量,如果即出现在左边又出现在右边,则表示被指物和指针两者都是常量

const int * 
int const * //注意这两种写法是一样的

const作为函数的返回值是为了避免函数的返回值因为编码错误而再被赋值。
const修饰成员函数代表该函数不可以更改对象的内容,并且可以通过这个函数操作const对象
使用mutable修饰成员变量,可以再const函数中修改此变量,打破在const成员函数中不可以修改成员函数的壁垒
这里总结一下const的用法:
(1)const修饰一般常量和数组表示,表示这些量的值不可以被修改
(2)const修饰指针变量:const如果出现在星号的左边 表示被指物是常量,出现在星号的右边表示指针自身是常量,如果即出现在左边又出现在右边,则表示被指物和指针两者都是常量
(3)const修饰引用 :

int const &a = x;
const int &a = x; //这两种方式的作用是相同的,即不可以通过引用a修改x的值 a++ 是错误的
int &const a = x;//这种方式没有定义,但是编译器不会报错,相当于 int &a = x;

(4)const 修饰函数参数:通常用于参数为指针或者引用的时候,表示传递进来的指针的内容或者引用的对象进行更改
(5)const修饰函数返回值:起到相应的保护作用:

const Rational operator*(const Rational& lhs, const Rational& rhs)
{
return Rational(lhs.numerator() * rhs.numerator(),
lhs.denominator() * rhs.denominator());
}
//返回值用const修饰可以防止允许这样的操作发生:
Rational a,b;
Radional c;
(a*b) = c;

(6)const修饰成员变量:表示成员变量不能被修改,同时只能在初始化列表中被初始化,因为常量只能被初始化,不能被赋值
(7)const修饰类的成员函数: 表示该成员函数不能修改类对象中的成员变量,若要修改要加上mutable修饰,一般const都写在函数的最后。
(8)const修饰类对象:该对象只能调用const成员函数,因为调用其他的函数可能会导致修改该对象的成员变量
const常量与define宏定义的区别:
  1)处理阶段不同:
  define是在预处理阶段,define常量从未被编译器看见,因为在预处理截断就已经替换了;
  const常量在编译阶段使用。
  2)类型和安全检查不同
  define没有类型,不做任何检查,仅仅是字符替换,没有类型安全检查,并且在字符替换时可能会产生意料不到的错误
  const常量有明确的类型,在编译阶段会进行类型检查;
  3)存储方式不同
  define是字符替换,有多少地方使用,就会替换多少次,不会分配内存;
  编译器通常不会为const常量分配空间,只是将它们保存在符号表内,使他们成为一个编译期间的一个常量,没有读取内存的操作,效率也很高;

const_cast:
用于修改类型的const或volatile属性。
用法:const_cast<type_id> (expression)
该运算符用来修改类型的const或volatile属性。除了const 或volatile修饰之外, type_id和expression的类型是一样的。
  1)常量指针被转化成非常量的指针,并且仍然指向原来的对象;
  2)常量引用被转换成非常量的引用,并且仍然指向原来的对象;
  3)const_cast一般用于修改底指针。如const char *p形式

条款04:确定对象被使用时已先被初始化
对于类构造函数,尽量使用初始化列表这样只调用一次copy构造函数,如果是在构造函数内部进行赋值的话,相当于调用了defaul构造函数和赋值构造函数
如果成员变量是const或者是references,他们就一定需要初值,不能被赋值。
成员初始化的顺序:基类先于派生类,class的成员总是以声明的次序被初始化
注意:不同编译单元内定义之 non-local static 对象的初始化顺序
将每个 non-local static 对象搬到自己的专属函数内,该对象在函数内被声明为static,这些函数返回一个reference指向它所含的对象,然后用户调用这些函数,而不直接支社这些对象 这样保证对象一定被初始化了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值