Effective C++ 03:尽可能使用const

       const允许你指定一个语义约束,而编译器会强制执行这项约束,确保某个对象不会被改变。
          如果某个对象在执行中 不应该( 或者 不会) 被改变,就应该使用const。
       
const的作用以及用法整理如下:

一、const修饰变量
    
    
#include<iostream>
using namespace std;
int main() {
int a=1; //non-const data
const int b=a; //const data
int *c = &a; //non-const data,non-const pointer
const int *d = &a; //const data,non-const pointer
int * const e = &a; //non-const data,const pointer
const int * const f = &a; //const data,const pointer
const int * const g = &a; //const data,const pointer
return 0;
}
          const修饰指针的时候,const在*号右边表示指针是const的,在*左边,表示*p即指针指向的对象,是const的。在STL迭代器的应用中, map<int, int>::const_iterator itr相当于const T* itr,即迭代器(指针)itr指向的对象*itr是const的,而 const map<int, int>::iterator itr 相当于T* const itr,即迭代器itr是const的。
         在上边代码中,若a的值被改变了,那么除b外,*c,*d,*e,*f,*g都会改变,因为b的赋值是copy赋值立即数,之后的b就跟a没有关系了,但对c-g而言,修饰它们的const仅仅表示,不能修改指针的值或者通过*p修改指针指向的变量,但a并不是const data,所以可以通过修改a的值来改变指针cdefg指向的值。
         使用const需要注意,const对象必须初始化(因为它不能改变不能接受再次的赋值)(但并不一定在声明的同时给予初值)。在函数中声明const需要立即给初值,在类class中声明的时候,不能立即赋值,这是因为 const数据成员只在某个对象生存期内是常量,而对于整个类而言却是可变的(这点与static相反),类可以创建多个对象,相应的const成员的初始化 只能在类的构造函数的初始化表中进行:
   
   
class Stuff
{
public:
Stuff(int m) : max_num(m)
{ };
private:
const int max_num;
};
          要想建立在整个类中都恒定的常量,应该用类中的枚举常量或者static来实现。

二、 const修饰成员函数
          const 成员函数的声明:const 关键字只能放在函数声明的尾部!
  
  
int func() const {
return 0;
}
          const 修饰的成员函数不能修改这个类对象的任何的数据成员 (准确地说是非静态数据成员)。
          const 成员函数不能调用非 onst 成员函数,因为非 const 成员函数可以会修改成员变量。
          在设计类的时候,一个原则就是对于不改变数据成员的成员函数都要声明为const成员函数。有 const 修饰的成员函数(const 放在函数参数表的后面,而不是在函数前面或者参数表内),只能读取数据成员,不能改变数据成员;没有 const 修饰的成员函数,对数据成员则是可读可写的。
         这样做好处在于 ,首先,类的接口更容易被理解,一看便知函数是读操作还是有写操作;其次,将成员函数声明为 const 使得该函数操作 const 对象成为可能,因为常量(即 const)对象可以调用 const 成员函数,而不能调用非const修饰的函数。
         ps:之所以我们希望函数可以操作 const 对象是因为处于程序的效率考虑,传引用或者指针往往比传值要好,传引用的时候为了防止对象被修改,往往要声明为 const 引用或指针,const 对象不能调用非 const 函数,所以,尽可能的将只有读操作的函数声明为 const 函数。
          注意:两个成员函数如果只是常量性不同,是可以被重载的,原因在于函数的形参列表里隐藏有this指针,const函数里this指针是 指向const对象的指针,而非const函数里的this指针是 正常版本的指针。
   
   
#include<iostream>
using namespace std;
class Chinese {
public:
Chinese() {
personID = IdentityCardId;
IdentityCardId++;
}
int getNation() const{
cout << "CHINA ID : " << personID << endl;
IdentityCardId++;
return 0;
}
int getNation() {
cout << "china ID : " << personID << endl;
return 0;
}
private:
static int IdentityCardId;
int personID;
};
int Chinese::IdentityCardId = 1;
 
int main()
{
const Chinese LaoWang = Chinese();
LaoWang.getNation(); //输出CHINA ID:1,const对象LaoWang默认调用const成员函数,并且可以修改static变量 IdentityCardId
Chinese LaoSun = Chinese();
LaoSun.getNation(); //输出china ID:3,non_const对象LaoSun默认调用non_const的成员函数
return 0;
}
         const对象默认调用const成员函数,非const默认调用const成员函数, 类中只有一个函数存在的情况下(我们删掉non_const版本的getNation()),non_const的对象也 可以调用非const成员函数。

三、const修饰函数返回值
          如果给以“指针传递”方式的函数返回值加const 修饰,那么函数返回值(即指针)的内容不能被修改,该返回值只能被赋给加 const 修饰的同类型指针。例如函数
   
   
const char * GetString(void);
          如下语句将出现编译错误:
   
   
char *str = GetString();
          正确的用法是
   
   
const char *str = GetString();
          如果函数返回值采用“值传递方式”,由于函数会把返回值复制到外部临时的存储单元中,加const 修饰没有任何意义。
          例如不要把函数
  
  
int GetCnt();
            写成
  
  
const int GetCnt();
          同理不要把函数(T为自定义数据类型)
   
   
T getT(void);
         写成
   
   
const getT(void);

          如果返回值不是内部数据类型,将函数T getT(void) 改写为const T & getT(void)的确能提高效率。但此时千万千万要小心,一定要搞清楚函数究竟是想返回一个对象的“拷贝”还是仅返回“别名”就可以了,否则程序会出错。  
 
          函数返回值采用“引用传递”的场合并不多,这种方式一般只出现在类的赋值函数中,目的是为了实现链式表达。 (除了重载操作符外一般不要将返回值类型定为对某个对象的const引用!)
          例如:
class A
{
A & operate = (const A &other); // 赋值函数
};
A a, b, c; // a, b, c 为A 的对象
 
a = b = c; // 正常的链式赋值
(a = b) = c; // 不正常的链式赋值,但合法
如果将赋值函数的返回值加const 修饰,那么该返回值的内容不允许被改动。上例中,语句 a = b = c 仍然正确,但是语句 (a = b) = c 则是非法的。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值