高效C++编程学习笔记(一)

条款01.尽量以const,enum,inline替换#define

这样子能够是编译器有较好的较错机制

常量定义

#define ASPECT_RATIO 1,653
通常替换为
const double AspectRatio = 1.653

定义常量指针

相对于 const char* const authorName = "Scott Meyers";
使用 const std::string authorName( "Scott Meyers");

class专属常量

将常量的作用域现定于class内,将它成为class的一个成员

class GamePlayer{
private:
	static const int NumTurns = 5;		//常量声明式
	int scores[NumTurns];						//使用该常量
}

对于C++而言,所使用的东西都要有一个定义式。如果是个class专属常量又是static且为整数类(例如int,char,bool)可以无需提供定义式。
而定义时需要在实现文件(.cpp)实现

//该常量在声明的时候获得初值(5),定义时不可以再设初值。
const int GamPlayer::NumTurns;

而#define没有作用域,无法创建一个class专属常量,也无法提供封装性

当编译器不允许static整数型class常量完成“in class的初值设定”,可以改用所谓的“the enum hack”方法补偿。

class GamePlayer{
	private:
		enum{	NumTurns = 5 };
		int scores{NumTurns};
}

内联函数替代宏函数

以一个比较a与b的较大值调用f函数为例

#define CALL_WITH_MAX(a,b)	f( (a) > (b) ? (a) : b)
可以使用内联函数
template<typename T>
inline void callWithMax(const T& a,const T& b)
{	
	f(a > b ? a : b);
}

**因为callWithMax是一个真正的函数,遵守作用域和访问规则可以写一个“class内的private inline函数”**而宏函数这不可以。

条款03.尽可能的使用const

const允许你告诉编译器和其他程序员某值应该保持不变

类型变量const

char greeting[] = "hello";
char* p = greeting;				//non-const poniter.non-const data
const char* p = greeting;		//non-const pointer.const data
char* const p = greeting;		//const pointer,non-const data
const char* const p = greeting	//const pointer,const data

函数返回值为const类型

class Rational {...};
const Rational operator* (const Rational & lhs,const Rational& rhs);

可以防止出现如下的错误

Rational a,b,c;
...
if(a * b = c)		//其实想做一个比较判断

const 成员函数

const的成员函数的目的如下

  1. 使class接口比较容易被理解
  2. 使“操作const对象”成为可能

两个函数的常量性不同就能被重载
举例说明

class TextBlock{
	public:
	...
	const char& operator[](std::size_t position) const	//operator[] for const 对象
	{ return text[position];}
	char& operator[](std::size_t position)	//operator[] for non-const 对象
	{ return text[position];}
	private:
	std::string text;
}

TextBlock的operator[]可被这么使用

TextBlock tb("Hello");
std::cout << tb[0];			//调用non-const TextBlock::operator[]
const TextBlock ctb("World");
std::cout << ctb[0];			//调用const TextBlock::operator[]
tb[0] = 'x';							//没问题,写一个non-const TextBlock
ctb[0] = 'x';						//错误!——写一个const TextBlock

const成员函数的实质是不更改类中的任何成员变量。然而在一个只有指针隶属于对象,更改了“指针所指物”的成员还是能通过编制器的认证

对于想在const成员函数中修改成员变量而不编译报错,可以在成员变量前增加前缀mutable

在const和non-const成员函数中避免重复

一般const与non-const中除了返回的类型不同,代码的其它部分完全一致
为了避免代码的重复,以TextBlock类为例,op[]操作中还要进行边界检验,志记数据访问,检验数据完整性。

class TextBlock{
	public:
	...
	const char& operator[](std::size_t position) const
	{
		...		//边界检验
		...		//志记数据访问
		...		//检验数据完整性
		return text[ position ];
	}
	char& operator[](std::size_t position)	//现在调用const op[]
	{
		return 
			const_cast<char&>(static_cast<const TextBlock&>(*this)[position]);	//调用const op[]
	}
	...
};

其中涉及两个类型转换
static_cast<const TextBlock&>(*this)[position]将类强制转换为const类型,避免函数op[]无线嵌套自身,const_cast<char&>(…)将返回的const char& 去掉引用。

条款04.确定对象被使用前已被初始化

对于内置的类型可以手工初始化

int x = 0;
const char* text = "A C-style string";

类的初始化

对于一个类要区分初始化和赋值操作,以电话本为例

class PhoneNumber { ... };
class ABEntry {
	public:ABEntry(const std::string& name,const std::string& address, const std::list<PhoneNumber>& phones);
	private:
		std::string theName;
		std::string theAddress;
		std::list<PhoneNumber> thePhones;
		int numTimesConsulted;
};
//赋值操作
ABEntry(const std::string& name,const std::string& address, const std::list<PhoneNumber>& phones)
{
	theName = name;
	theAddress = address;
	thePhones = phones;
	numTimesConsulted = 01;
}
//初始化
ABEntry(const std::string& name,const std::string& address, const std::list<PhoneNumber>& phones)
:theName(name),
theAddress(address),
thePhones(phones),
numTimeConsulted(0)
{}					//构造函数本体不必有任何动作。
//ABEntry是一个无参构造函数,也可以使用默认构造一个成员变量
ABEntry::ABEntry()
	:theName(),			//调用theName的默认构造函数
	theAddress(),		//同上
	thePhones(),		//同上
	numTimesConsulted(0)	//将其显式初始化为0
{
}

相比于赋值操作,初始化效率更高。因此总是使用成员初值列。对于有多个构造函数的class,可以将"赋值表现像初始化一样好"的成员变量封装成私有函数供构造函数调用

初始化顺序

class的成员变量总是以其声明的方式被初始化化,与在成员初值中的次序出现无关。
对于全局定义的class,使用单例模式。

non-local-static对象

对于该类对象来说,在未初始化之前调用它会引发灾难性结果,一般使用单例模式来保持。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值