[C++]聊聊const
常量出现的motivation是:隐藏保证数据安全性,共享破坏安全性,对于既需要共享又要防止改变(保证安全)的数据可以声明为常量。常量在运行期不可改变。
给出xgboost中的部分代码(metric.h),不需要关注细节,感受下const的存在。
文章的关键词是:常对象,常成员(成员变量和成员函数),常引用,常指针。
常对象:对象不能被修改;只能调用常成员函数。
常成员函数:不会修改对象状态的函数都应该声明为常成员函数。
常引用:实参不会被修改且实参较大(比如,一个很大的vector作为实参传递)。
指向常量的指针:指针可变,指针指向内容不可变。
指针常量:指针不可改变。
给出一个示例代码,包含了上述几个问题,如果代码调试通过,就可以认为基本理解了上述内容(代码中有广告植入)。
重点谈常引用。上述代码第17行:
const string& getVersion() const {return this->version;}
在该行代码中,getVersion()作为成员函数,目的是返回对象的成员变量version。因为没有修改对象状态,故应该声明为常成员函数,也就是在函数声明后加关键字const,返回类型是** const string&**,也就是对string类型变量的常引用。为什么?
常引用表示对象状态不可以被修改,也就是函数的返回值不可以被修改。如果去掉const,返回一个普通string类型的引用,则由于采用了引用的方式返回值,对象的数据成员可以被修改,和常成员函数的初衷就违背了。
bool compare(const string& owner){return owner == this->author ? true : false;}
这行代码的亮点在于形参的表示const string& owner。为什么使用引用方式?假设string类型实参较大,实参传值给形参的复制操作,耗时较长。采用引用方式直接访问实参对应内存区域,避免复制操作。为什么要用const修饰?上述代码实参可以是const也可以是非const。如果没有const修饰,就不能接受const类型实参了。类似的,对于常成员函数,非const类型对象和const类型对象都可以使用,要知道,const对象只能访问const函数。
总结:已经没有什么要说的了,回头看看xgboost中的metric.h中的那几个const,对照刚刚谈到的一些东西,或许就会有一些新的感受。