const 用法及常见错误

原帖地址:http://hi.baidu.com/sysucs/blog/item/98f39c356f5b451391ef397e.html

2007-08-02 23:45

自己在VCKBASE上,总是听到有人问 const int *p 与 int const *p 与 int *const p 有什么区别,我自己也回答了很多次,这次又看到有人问,想想自己应该记录下来,虽然这个问题很简单,几乎每一本讲 C 基础的书上都会说明。
  自己还没有(也不能完成)仔细的说出 const   有几种用法,但是我下面将会说出我所知道的用法。
下面的代码,使用 VC6 在 WindowsXP 上编译运行

1、用作变量修饰符
  const可以在定义变量时作为修饰符,用来表示该变量不可修改。需要注意的是:const修饰某个变量时,总是限定const所处位置的右侧。例如代码 const int nc = 0 ;   用来声明一个整型常量 nc,这个常量不可更改。假如执行下面的语句

  1. int main(int argc, char* argv[])
  2. {
  3.    const int nc = 0;
  4.    nc = 1;        //修改了常量 nc,不能编译过去
  5.    return 0;
  6. }

编译时会报错“l-value specifies const object”
需要说明的是,声明变量时,const int nc = 0
i nt const nc = 0 意义是一样的,个人推荐使用后面一种 i nt const nc = 0 ,这样别人在看代码的时候,可以先很快的知道 nc 是常量。
大家看完我上面所说的,可能更好的理解下面我所说的 int const *p 与 int *const p 的区别。
前面我也说了,const 是修饰它位置右侧的,所以 int const *p 主要是修饰 *p 为常量,也就是说 *p 的值不能改变;而 int *const p 则是修饰 p 为常量,也就是说指针 p 为一个常量指针。可以根据下面的代码来加深印象

  1. int main(int argc, char* argv[])
  2. {
  3.    int n = 0;
  4.    int m = 1;
  5.    int const *p1 = &n;
  6.    int * const p2 = &n;
  7.    p1 = &m;
  8.    (*p1) = m;  //这里编译出错,错误为 “error C2166: l-value specifies const object”
  9.    p2 = &m;    //这里编译出错,错误为 “error C2166: l-value specifies const object”
  10.    (*p2) = m;
  11.    return 0;
  12. }

执现在大家该明白了 int const *p 与 int *const p 两者之间的区别了吧。
好了,我们又回到上面的代码。去除了两行编译错误的行后,可以正确的编译并运行。调试信息如下所示:

 

  1. int main(int argc, char* argv[])
  2. {
  3.    //说明: 下面的注释(以 //D 开头)都是对上面语句执行后的注释
  4.    int n = 0;
  5.    int m = 1;
  6.    //D &m = 0x0012ff78
  7.    //D &n = 0x0012ff7c
  8.    int const *p1 = &n;
  9.    //D p1 = 0x0012ff7c, (*p1) = 0
  10.    int * const p2 = &n;
  11.    //D p2 = 0x0012ff7c, (*p2) = 0
  12.    p1 = &m;
  13.    //D p1 = 0x0012ff78[改变], (*p1) = 1[改变]
  14.    (*p2) = m;
  15.    //D p2 = 0x0012ff7c[未改变], (*p2) = 1[改变]
  16.    //D 注意,这时候, n 的值改变了, n = 1[改变]
  17.    //D p1 与 *p1 都未改变
  18.    return 0;
  19. }

2、用来修饰函数
const 用来修饰函数,有两种情况

  1. int const foo1()
  2. {
  3.    return 0;
  4. }

  1. int CXXX::foo2() const
  2. {
  3.    return 1;
  4. }

不过,上面的那种情况,一般是使用在函数的返回值为一个指针的情况下,告诉编译器(或者说是编码人员),请不要修改我这个函数的返回值,否则有可能出错;下面的那种情况,只能是用在一个类成员函数中,不能用在普通的函数中,作用是告诉编译器,我这个函数体中,不会修改任何同类(都是类 CXXXX)的任何变量。下面我来列出代码说说情况。我写了下面的代码:

 

  1. class CXXX{
  2. public:
  3.    //构造函数与析构函数 
  4.    CXXX();
  5.    ~CXXX();
  6.    //外部调用的函数 
  7. public:
  8.    int foo();
  9.    int const foo1();
  10.    int fooc() const;
  11.    int const *foop();
  12. protected:
  13. private:
  14.    //成员变量 
  15. public:
  16.    int m_public;
  17. protected:
  18.    int m_protected;
  19. private:
  20.    int m_private;
  21. };
  22. CXXX::CXXX()
  23. {
  24.    m_public = 0;
  25.    m_protected = 1;
  26.    m_private = 2;
  27. }
  28. CXXX::~CXXX()
  29. {
  30. }
  31. int CXXX::foo()
  32. {
  33.    m_public     += 100; // 编译不会产生任何的错误 
  34.    m_protected += 100; // 编译不会产生任何的错误 
  35.    m_protected += 100; // 编译不会产生任何的错误 
  36.    return 0;
  37. }
  38. int const CXXX::foo1()
  39. {
  40.    m_public     += 100; // 编译不会产生任何的错误 
  41.    m_protected += 100; // 编译不会产生任何的错误 
  42.    m_protected += 100; // 编译不会产生任何的错误 
  43.    return 1;
  44. }
  45. int CXXX::fooc() const
  46. {
  47.    m_public     += 100; // error C2166: l-value specifies const object 
  48.    m_protected += 100; // error C2166: l-value specifies const object 
  49.    m_protected += 100; // error C2166: l-value specifies const object 
  50.    return 2;
  51. }
  52. int const *CXXX::foop()
  53. {
  54.    return &m_protected;
  55. }
  56. int main(int argc, char* argv[])
  57. {
  58.    CXXX myclass;
  59.    int n = myclass.foo();
  60.    n = myclass.foo1();          // 正确。请注意这一行,调用的函数 int const CXXX::foo1() 
  61.    n = 1000;    // 正确 
  62.    int const nc = myclass.foo1();
  63.    int *p = myclass.foo();     // error C2440: 'initializing' : cannot convert from 'const int *' to 'int *' 
  64.    const *pc = myclass.foop(); // 正确 
  65.    return 0;
  66. }

具体的,我在上面的代码中已经注释出来了,详细的我就不再说明。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值