每天学习一个C++提升的小技巧:条款02:尽量用const,enum,inline 替换#define。

本博文以及这个系列的都是我本人观看《Effective C++》的观后感,每天学习一个改善自己C++的一个小技巧。

条款02:尽量用const,enum,inline 替换#define。


*/
#include<iostream>
using namespace std;
#define PI 3.14    //宏常用大写
/*
* 记号名称PI也许从未被编译器看见,也许在编译器开始处理源码的时候之前就被预处理器移走了。于是记号名称PI很可能没有进入记号表内。
当你运用此常量但获得一个编译错误的时候,也许会困惑,因为这个错误的信息也许提到了3.14而不是PI。如果PI被定义在其他非你写的头文件内,你肯定对3.14以及它来自何处好无概念,
被你追踪它而浪费时间。
*/

//解决的方法用一个常量替换上面的宏

const double Pi = 3.14;

/*作为一个语言常量,Pi肯定会被编译器看到,就会进入记号表。此外,使用常量可能比使用#define的代码量小,
因为预处理器“盲目地将宏PI替换成3.14”可能导致目标代码出现多份3.14,改用常量pi绝对不会出现相同情况。

*/




/*
* 以常量替换#define有两种特殊情况:
* 1.定义常量指针。以便被不同源码含入,常量定义式通常被放在头文件内,所以有必要将指针声明为const。
* 
*/

const char* const Name1 = "Gentle";   //必须加上两个const
const std::string Name2("Gentle");

/*
	2.class专属常量。为了将常量的作用域限制在class内,你必须让它成为class的一个成员,为了确保此常量只有一份实体,你必须声明为static成员

*/

/*
* 无法利用#define创建一个class专属的常量,因为#define不重视作用域。一旦被宏定义,它就在其后的编译过程中有效。
#define不仅不能用来定义class的专属常量,也不能提供任何封装性。
*/
class Person
{
    
    
private:
		static const int m_number = 3;   //常量声明式
		int m_scores[m_number];				//使用常量

};
/*
* 通常C++要求你对你使用的任何东西提供一个定义式,但它如果是class的专属常量又是const且是int类型,则特殊处理。只要你不取它得地址,你可以声明而无须提供定义式。
* 下面是补充该定义式
*/

const int Person::m_number;      //m_number的定义,因为常量声明的时候已经给出初始值,所以这里不用初始化。



//上下两段代码类似,上面是先赋予初始值,下面是后赋予初始值



/*
* 
*/

class Golden    //位于头文件内
{
    
    
	//...
private:
	static const double m_rate;
	//....
};

const double Golden::m_rate = 0.618;  //定义在实现文件内



/*也可以用“the enum hack”补偿(一个属于枚举类型的数值可以充当int型被使用)做法完成 class Person初始值设定
*/
class Person1
{
    
    
private:
	enum{
    
    m_number = 5};     //令m_number成为5的一个标记
	int m_score[m_number];
};
	
/*enum hack的行为比较像#defien而不像const,取const的地址是合法的,取enum的地址是不合法的,而取一个#define的地址通常也不合法。
如果不想别人获得一个指针或引用指向你的某个整数常量,enum可以帮你实现这个约束。enum hack是模板元编程的基础技术*/

另一个宏常见的错误

#include<iostream>

using namespace std;
/*
* 另一个宏常见的错误
*/

//以a和b比较的较大值调用f
#define CALL_WITH_MAX(a,b) f((a)>(b)?(a):(b))   //每个参数都得带上小括号

void f(int x)
{
    
    
	cout << x << endl;
}
int main()
{
    
    
	int a = 5, b = 0;
	CALL_WITH_MAX(++a, b);
	cout << "a: " <<a<< endl; //a被累加了两次
	CALL_WITH_MAX(++a, b + 10);//a累加了一次
	cout << "a: " <<a<< endl;
}

执行效果
在这里插入图片描述
在这里,调用f之前,a的递增次数竟然取决于它跟谁比较!!!!!!
为了获得宏带来的执行效率和一般函数的所以可预料行为和安全性,我们要用内联函数模板。

void f(int x)
{
    
    
	cout << x << endl;
}

template<typename T>
inline void CallWithMax(const T& a, const T& b)
{
    
    
	f(a > b ? a : b);
}
int main()
{
    
    
	int a = 5, b = 0;
	CallWithMax(++a, b);
	cout << "a: " <<a<< endl; 
	CallWithMax(++a, b + 10);
	cout << "a: " <<a<< endl;
}

执行效果
在这里插入图片描述

请记住

  • 对于单纯的常量,最好以const对象或enum替换#define。
  • 对于形式函数的宏,最好用inline函数替换#define.

猜你喜欢

转载自blog.csdn.net/weixin_50188452/article/details/111036041