如下两个跟踪类:
(1)采用const string&传递参数。
class Trace
{
public:
Trace(const string& name):theFunctionName(name)
{
if(traceIsActive)
{
cout<<"Enter funciton"<<theFunctionName<<endl;
}
}
~Trace()
{
if(traceIsActive)
{
cout<<"Exit function: "<<theFunctionName<<endl;
}
}
void debug(const string& theMsg)
{
if(traceIsActive)
cout<<theMsg<<endl;
}
static void setTraceState(bool bActive)
{
traceIsActive=bActive;
}
private:
string theFunctionName;
static bool traceIsActive;
};
(2)用const char*传递参数。
class Trace
{
public:
Trace(const char* name):theFunctionName(NULL)
{
if(traceIsActive)
{
cout<<"Enter function:"<<name<<endl;
theFunctionName=new string(name);
}
}
inline ~Trace()
{
if(traceIsActive)
{
cout<<"Exit function: "<<*theFunctionName<<endl;
delete theFunctionName;
}
}
inline void debug(const char* theMsg)
{
if(traceIsActive)
{
cout<<theMsg<<endl;
}
}
static void setTraceState(bool bActive)
{
traceIsActive=bActive;
}
private:
string* theFunctionName;
static bool traceIsActive;
};
两个类中关于是否跟踪的标识定义如下:
bool Trace::traceIsActive=false;
执行一个简单的加法函数,重复一百万次。函数定义如下:
int addOne(int x)
{
char* name="addOne";
Trace t(name);
return x+1;
}
调用代码如下:
#define COUNT 1000000
int _tmain(int argc, char* argv[])
{
Trace::setTraceState(false);
clock_t start=0;
clock_t finish=0;
start=clock();
for(int i=0;i<COUNT;i++)
{
addOne(i);
}
finish=clock();
double duration=(double)(finish-start)*1000/CLOCKS_PER_SEC;
cout<<"total time:"<<duration<<"ms"<<endl;
return 0;
}
用第一个采用const string&的类,耗费的时间为4240ms,即在千毫秒级。
用第二个采用const char*作为参数,并且在类内部采用string*,则耗费的时间为124ms,在百毫秒级。
分析原因:
在addOne中,第一种情况下:
(1)传递参数的过程,会根据name构造一个临时的string对象。
(2)调用Trace的构造函数,这个构造函数会调用内部成员theFunctionName的构造函数,构造一个string对象。
(3)函数执行结束要销毁两个string对象,销毁构造的Trace对象。
即使在不跟踪的情况下也要付出以上的额外开销。
第二个则只是在确定需要跟踪的情况下,才构造一个string对象。
如果能够增加一个调用是否跟踪的借口,则可免去Trace对象的构造。但是引起的问题就是,是否跟踪之间切换状态时,会需要重新编译程序,这个开销也不小。
总结:还是采用const char*传递的参数最为佳,不提供是否跟踪之间状态的切换。