effective c++第一章

一、理解c++

1、c:c++仍是以c为基础的,块、语句、预处理、内置数据类型、数组、指针等都来自c

2、Object-Oriented c++:c with classes,classes包括构造函数、析构函数、封装、继承、多态、虚函数等

3、Template c++: c++泛型编程

4、STL: c++template程序库,对容器、迭代器、算法以及函数对象的规约

二、尽量以const、enum、inline替换#define

三、由于常量定义通常被放在头文件内,因此有必要将指针声明为const

四、为了将常量的作用域限制于class内,通常让常量成为一个static

五、无法利用#define创建要给class常量,因为#define不重视作用域

六、取一个const地址是合法的,但取一个enum的地址就不合法,取一个#define的地址通常也不合法

七、对于单纯常量,最好以const对象或enum替换#define

八、对于形如函数的宏,最好用inline函数替换#define

九、尽可能使用const, const告诉编译器和程序员其值应该保持不变

十、const与*

1、关键字const出现在星号左边,表示被指物是常量

2、关键字const出现在星号右边,表示指针自身是常量

3、关键字const出现在星号两边,表示被指物和指针自身都是常量

十一、迭代器的作用就像个T*指针,声明迭代器为const表示这个迭代器不得指向不同的东西,但它所指向的东西的值是可以改动的

十二、如果希望迭代器所指的东西不可被改变,需要使用const_iterator

十三、mutable修饰成员变量表示总是会可以被修改,即使在const成员函数内

十四、将某些东西声明为const可帮助编译器检测出错误

十五、当const和non-const成员函数有着实质等价的实现时,可以令non-const版本调用const版本消除代码重复

十六、对象的成员变量的初始化动作发生在进入构造函数本体之前,发生于default构造函数被自动调用时

十七、基于赋值的构造函数首先调用default构造函数为成员变量设初始值,然后立即再对它们赋予新值

十八、如果成员变量时const或references,它们就一定需要初值,而不是被赋值

十九、base classes早于derived classes被初始化; class的成员变量总是以其声明的顺序被初始化

二十、构造函数最好使用成员初值列,而不要在构造函数本体内使用赋值操作。初值列列出的成员变量,其排列顺序应该于它们在class中声明的顺序相同

二一、为免除“跨编译单元之初始化次序”的问题,尽量以local static对象替换no-local static对象

 

// 常量指针: 由于常量定义通常放在头文件内,因此有必要将指针声明位const

// 定义一个常量的char* 字符串,必须写2次const
const char* const authorName = "Sccott Meyers";
// 而对于c++,使用string更合适
const std::string authName1 = "Sccott Meyers";

// 对于单纯常量,最好以const对象或enum替换#define
// 对于形似函数的宏,最好改用inline函数替换#define
#define CALL_WITH_MAX(a, b) f((a) > (b) ? (a) : (b))
template<typename T>// 由于不知道T是什么,所以采用pass by reference-to-const
inline void callWithMax(const T& a, const T& b)
{
	f(a > b ? a : b);
}


class GamePlayer
{
private:
	// 为了将常量的作用域限制于class内,必须让它成为class 的一个成员
	// 而为了确保此常量至多只有一份实体,必须让它成为一个static成员
	static const int numTurns = 5;
	enum { numTurns2 = 5 };
};

class TextBlock
{
public:
	const char& operator[](size_t position) const
	{
		// ...边界检验
		// ...数据完整性检验
		return text[position];
	}
	char& operator[](size_t position)
	{
		// ...边界检验
		// ...数据完整性检验
		//return text[position];

		// 大量代码重复,这种情况下,如果将返回值的const转除是安全的
		// 当const和non-const成员函数有着实质等价的实现时,可令non-const版本调用const版本避免代码重复
		// 但切记不能令const版本调用non-const版本,因为const成员函数承诺不改变其对象的逻辑状态,而这样做对象有可能因此被改动
		//可以令non-const operator[]调用const operator[],这个过程需要一个转型
		// 将operator[]返回值的const转除
		//const_cast 修改类型的const或volatile属性。使用该运算方法可以返回一个指向非常量的指针(或引用)
		return const_cast<char&>( 
			// 为*this加上const, 将*this从其原始类型TextBlock&转换为const TextBlock&
			//static_cast 用于良性转换,一般不会导致意外发生,风险很低。
			static_cast<const TextBlock&>(*this)
			[position] // 调用const operator[]
			);
	}

private:
	string text;
	mutable size_t textLength; //mutable成员变量总是可以被改变,即使是在const成员函数内
};

class PhoneNumber
{

};

class ABEntry
{
public:
	ABEntry(const string& name, const string& address, const list<PhoneNumber>& phones);
private:
	string theName;
	string theAddress;
	list<PhoneNumber> thePhones;
	int numTimesConsulted;
};

// 构造函数初始化和赋值的区别
ABEntry::ABEntry(const string& name, const string& address, const list<PhoneNumber>& phones)
{
	// 赋值而非初始化
	theName = name;
	theAddress = address;
	thePhones = phones;
	numTimesConsulted = 0;
}
// 对象的成员变量的初始化动作发生在进入构造函数本体之前,发生于这些成员的default构造函数被自动调用之时
// 基于赋值的版本首先调用default构造函数为成员变量设初始值,然后立即再对它们赋予新值
ABEntry::ABEntry(const string& name, const string& address, const list<PhoneNumber>& phones)
	// 这是初始化
	: theName(name)
	, theAddress(address)
	, thePhones(phones)
	, numTimesConsulted(0)
{

}


int main()
{

	char greeting[] = "hello";
	char* p = greeting; // non-const pointer, non-const data
	// 关键字const出现在星号左边,表示被指物是常量
	const char* p = greeting; // non-const pointer, const data
	// 关键字const出现在星号右边,表示指针自身是常量
	char* const p = greeting; // const pointer, non-const data
	// 关键字const出现在星号两边,表示被指物和指针都是常量
	const char* const p = greeting; // const pointer, const data

	// 迭代器的作用就像个T*指针
	// 声明迭代器为const表示这个迭代器不得指向不同的东西,但它所指的东西的值是可以改动的
	// 如果希望所指的东西不可被改动,需要使用const_iterator
	vector<int> vec;
	// iter的作用像个T* const: T* const iter; 在星号右边,表示指针自身是常量
	const vector<int>::iterator iter = vec.begin();
	// 改变iter所指的东西
	*iter = 10;
	// 错误, iter是const
	//++iter;
	// cIter的作用像个const T*: const T* cIter; 在星号左边,表示被指物是常量
	vector<int>::const_iterator cIter = vec.begin();
	// 错误,*cIter是const
	//*cIter = 10;
	++cIter;


	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值