用const和inline代替define
发现问题:
编程的时候现在文件的头部定义了
#define defaultsize 1000
后来在main函数里面写
for(int i=0;i<defaultsize;i++)时候发现编译器一直提示 错误,
后来查阅了相关资料把定义改为
const int defaultsize 1000 错误就消失了!
解决问题:
define的使用一般有几种情况:
1. 用来定义常量,如
#define pi 3.1415926
2. 用来定义小函数,如
#define max(a,b) ((a) > (b) ? (a) : (b))
3. 用于
#ifndef _DEBUG
...
#endif
这样的组合
对于第一种情况,可以用const代替;第二种情况可以用inline来代替;第三种情况现在还没有其它方案
用const代替define来定义常量
因为define定义常量只是在编译之前用其值来代替符号(如上面的例子中是用3.1415926代替 pi ),所以如果在编译时出了错误,错误可能比较难发现。因为编译器只看到3.1415926这个数,而看不到 pi 这个符号,所以提示信息里很可能只会告诉你3.1415926这个数出现的地方有错,这时你就得去找3.1415926这个数到底在哪里定义的。
而如果用const float pi=3.1415926来定义就要简单得多了,出错信息会告诉你是 pi 出了错,这就简单多了。
用inline代替define来定义函数
define定义函数的最大缺点就是它只是简单替换,所以函数的参数可能会改变函数的行为。
比如上面定义的max,如果有这么一段代码:
int a = 5, b = 0;
max(++a, b); // a is incremented twice
max(++a, b+10); // a is incremented once
可以看到对两次调用,++a执行的次数是不一样的。而如果用inline,写成如下形式:
inline int max(int a, int b) { return a > b ? a : b; }
就不会有这个问题了。
其它相关问题
在class里定义常量
有时候我们希望常量只在一个类里有效,比如:
template <class T>
class set{
static const int DefaultSize=10;
public:
set(){data=new T[DefaultSize];}
protected:
T * data;
}
按照标准,还应该在实现文件里加一句
const int set::DefaultSize;
但即使不加,这样的语法在VC++.NET里也不会出错。
在一些比较古老的编译器里这样的语法就会出错了,比如在VC++6.0里就不行,它不允许在类的声明文件里初始化 DefaultSize,所以我们只能这么写:
template <class T>
class set{
static const int DefaultSize;
public:
set(){data=new T[DefaultSize];}
protected:
T * data;
}
然后在类的实现文件里写
const int set::DefaultSize=10;
但这里又有个问题,如果我们的代码这么写,就出问题了:
template <class T>
class set{
static const int DefaultSize;
protected:
T data[DefaultSize];
}
在初始化 data 时,DefaultSize 还没被赋值。怎么办呢,只能这么写了:
class GamePlayer {
private:
enum { NUM_TURNS = 5 }; // "the enum hack" — makes
// NUM_TURNS a symbolic name
// for 5
int scores[NUM_TURNS]; // fine
...
};
这个方法很易做图,但这也是没办法的办法了。
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
条款1:尽量用const和inline而不用#define
尽量用编译器而不用预处理
特殊情况:
1.指针常量,比如字符串常量
const char * const authorName = "Scott Meyers";
2.某个类的常量,放在内部并且定义为静态成员
class GamePlayer{
private:
static const int NUM_TURNS = 5; // constant eclaration
int scores[NUM_TURNS]; //use of constant
...
};
//注意,上面的是对NUM_TRUNS的声明,需要单独定义:
const int GamePlayer::NUM_TURNS; //mandatory definition;
旧一点的编译器会不接受这种语法,因为它认为类的静态成员在声明时定义初始值是非法的;而且,类内只允许初始化整数类型(如:int, bool, char 等),还只能是常量。
在上面的语法不能使用的情况下,可以在定义时赋初值:
class EngineeringConstants { // this goes in the class
private: // header file
static const double FUDGE_FACTOR;
...
};
// this goes in the class implementation file
const double EngineeringConstants::FUDGE_FACTOR = 1.35;
为了弥补那些(不正确地)禁止类内进行整型类常量初始化的编译器的不足,可以采用称之为“借用enum”的方法来解决。这种技术很好地利用了当需要int类型时可以使用枚举类型的原则
class GamePlayer { www.zzzyk.com
private:
enum { NUM_TURNS = 5 } // "the enum hack" — makes
// NUM_TURNS a symbolic name
// for 5
int scores[NUM_TURNS];// fine
};
宏定义的类似函数的东西,可以用模板取代:
template<class T>
inline const T& max(const T& a, const T& b)
{ return a > b ? a : b; }
补充:综合编程 , 其他综合 ,