C++ 进阶 - const 的用法及尽量使用const的好处

文章有点长哈,可以耐心的看看。个人总结,请持怀疑态度参考。
文章中代码的测试环境为 VS2013

进入正题。。。。

const关键字在C++中的用法多种多样,可以概括如下:

  • 它可以在classes外部修饰global或namespace作用域中的常量或者修饰文件、函数或者块作用域中被声明为static的对象。
  • 它也可以修饰classes内部的静态成员和非静态成员变量。

一、修饰指针

在修饰指针时首先要明确 const是修饰的指针自己(pointer),还是修饰的指针所指向的东西(data)。

贴一段代码

#include
using namespace std;
int main()
{

    /*int num = 123;
    int *p = #
    *p = 222;
    cout << num << endl;    */


    /*1. non-const pointer  ; const data*/

    /*int num = 123;
    const int *p = #
    // *p = 222;   //报错  
    int num_s = 77;
    p = &num_s; 
    cout <<*p<< endl;*/


    /*2.  const pointer  ; non-const data*/

    /* 
    int num = 123;
    int * const p = #
    *p = 222;
    cout << num << endl;
    int num_s = 555;
    p = &num_s;   //报错
    */


    /*3.  const pointer ; const data*/

    /*int num = 123;
    const int * const p = #
    *p = 222;   //报错
    int num_s = 77;
    p = &num_s;   //报错
    cout << num << endl;*/


    getchar();
    return 0;
}

可以用这段代码测试一下,代码中有注释如何修饰pointer和如何修饰data

总之:
如果const出现在左边 则指针指向的东西为常量,即修饰的是 data;如果const出现在 右边 则 指针本身为常量,不可修改,即修饰的是 pointer。


二、修饰STL迭代器

STL迭代器就像一个模拟的指针
- 如果你希望迭代器的指向不发生改变,即类似与 T*const 的作用,那么你可以这样写:const std::vector:: iterator iter=a.end()
- 如果你希望迭代器指向的值不发生改变,那么应该用 const_iterator 。

贴一段代码:

    list<int> a;
    a.push_back(1);
    a.push_back(2);

    /*const list::iterator iter = a.begin();
    *iter = 5;
    iter=a.end();   //报错   因为这个迭代器是常量   */

    list<int>::const_iterator iter = a.begin();
    *iter = 5;  //报错   因为这个迭代器指向的值是常量
    iter = a.end(); 

三、修饰成员函数

修饰成员函数的用法就不重复说了,可以看我的这篇博客点击这里

重点说一下 const成员函数的重要性 与 如何优化 同一个函数const 和 non-const 两个版本的代码(const ,non-const 是可以重载的 )

+——

1.const成员函数的重要性

//A.h
class A
{
public:
    MyClass(){ };
    ~MyClass(){};
    int dis() const;
    int dis();
    .....
private:
    ......
};

//main.cpp
void print(const A & a)
{
    a.dis();   //调用const版本  
}

int main()
{ 
    ....
 }

必须重载dis() 并对不同版本给予不同的处理

+—-

2.如何突破const对成员函数的限制

在C++中,mutable可以突破const的限制。被mutable修饰的变量,将永远处于可变的状态,即使在一个const函数中。

为什么需要突破限制呢?
需要考虑到 某个函数 对客户(调用者)来说是不会修改任何数据的,但是实际上在实现这个函数是仍然有修改某些值的需要(只不过对客户来讲是不可见的,无法察觉的,也是没必要关心的)

举个栗子:
你要写一个处理文本的类,让后类中需要有 返回文本字数的 成员函数。这个函数显然是不会修改客户的文本数据的,so 声明为const ,给客户承诺,我是不会改你的数据的 。但是实现代码时仍然有私有变量需要改动!!

贴代码:

class Text
{
public:
    Text(){ len_flag = false; };
    ~Text(){ };
    size_t length() const
    {
        if (!len_flag)
        {
            text_len_new = strlen(text);  //注意这两行
            len_flag = true;  //  ...  
        }
        return text_len_new;
    }

private:
    mutable size_t text_len_new;  //最近一次计算的长度
    mutable bool len_flag;   //目前的长度是否有效   
    char *text;
};

int main()
{
    Text t;
    t.length();   //不会该数据,可以放心使用  
}

+—–

3.在const 和 non-const中避免代码重复
(虽然相同的代码可以复制粘帖,但是代码重复太多显的很乱,而且不好维护!)
假如在上面的那个文本处理类中加一个成员 用来格式化显示文本,并且检查文本中是否有错误的内容

贴代码

    const char* dis_text() const
    {
        /*
        一大块验证字符串合法和格式化等等代码
        */
        return this->text;
    }
    char * dis_text()
    {
        /*
        一大块验证字符串合法和格式化等等代码
        */
        return this->text;
    }

可以发现这两个版本的代码除了返回值不同,其他的都一样!!如何处理这么多的重复代码?
直接把相同的代码打包成一个函数,让后调用不就行了。其实这样做也可以,不过不是做好的做法,应函数调用需要有开支啊 。。

解决方法 ,应用c++标准类型转换 ,一共有 4 种转换,可以自行百度一下 。用non-const的版本调用const的版本就可以了,有人可能不解,为什么要类型转换?HI 兄弟 你那么努力是在写BUG啊 !如果直接调用 是不会发生重载的,相当与没有结束条件的递归调用!!!!

注意:轻易别使用这种转换,玩不好就会危险。
贴代码:

    const char* dis_text() const
    {
        /*
        一大块验证字符串合法和格式化等等代码
        */
        return this->text;
    }
    char * dis_text()
    {
        return const_cast<char*>(    
         //const_cast   把const修饰的给去掉   
            static_cast<const Text&>(*this).dis_text()   
            //把*this 转为 const 类型的对象 然后调用 dis_text()const 的版本
            );
    }

注意:不要调用反了,不要用const 调用non-const !!non-const可没有承诺说不改数据,如果反着调用const就很被动,鬼知道你在non-const中有没有改数据!


四、const修饰返回类型

这一点也是很重要的 ,主要是针对返回 指针 引用!使用 const限制 可以避免很多安全隐患,甚至是你在写代码时不小心手抖写错的问题!
例如 类A 有重载 * 、 = 运算符 如果没有限制 在不经意间可能写出如下代码 :

A a(1);
B b(2);
if(a+b=5)   //计划写 a+b==5  比较   
{
}

这种被隐式转换为bool类型的bug也不好找 。。。。。


我的个人网站 http://www.breeziness.cn/
我的CSDN http://blog.csdn.net/qq_33775402
转载请注明出处 小风code www.breeziness.cn

你可能感兴趣的:(C/C++进阶,C++学习之路,C++,c++const用法,使用const的好处)