C++ const

来源:互联网 发布:丹尼斯·约翰逊数据 编辑:程序博客网 时间:2024/04/27 23:39

目的: 值代替。 

预处理宏定义的缺点: 只做文本替换,并没有类型检查,这样会产生风险。


      

内存存储形式,常量折叠

常量的定义会保存在符号表中,可折叠的常量像宏一样,在预编译阶段对常量的引用一律被替换为常量所对应的值。但在运行时常量也是会被分配内存空间的。

下面的程序可以说明。 

    int main()      {          const int i=0;        int *j = (int *) &i;        *j=1;        printf(" addr_i=%d\n addr_j=%d\n val_i=%d\n val_j=%d\n",&i,j,i,*j);        return 0;      }

运行时指针j是可以取得常量i的地址,但无法修改地址中的值,原因是预编译时常量i已经通过常量折叠进行了替换,
在运行时用到i的地方已经替换为0,但i在内存中还是被分配了空间的。


使用形式:

    1) 普通常量

        const int ArrSize=10;
        int arr[ArrSize];

    2) 常量集合

   常量也可以用于集合,但集合无法被放入符号表中,必须分配内存。此时常量的含义是 "不能改变的一块存储"。

        // 正确
const int SizeArr[] = {1,2,3,4};

// 下面的使用方法是错误的
                float farr[SizeArr[2]];   //错误
原因: 常量集合SizeArr无法被保存到符号表中,所以预编译时无法对SizeArr[2]进行替换。

                从编译时提示的错误信息也可以看的很清楚
                error C2057: expected constant expression
                error C2466: cannot allocate an array of constant size 0
                error C2133: 'farr' : unknown size

    3) 指针

                指向const指针    const int* x;     int const* x;
一个指针,指向一个const 变量, 不需要初始化,可以指向不同的常量。  地址可变::值不可变

        const int i=10;        const int j = 100;        const int* x;    x = &i;cout << *x << endl;        x = &j;cout << *x << endl;*x = 5;   //  错误 error C3892: 'x' : you cannot assign to a variable that is const

        const 指针    int* const x;

指针本身为const指针,指针指向的地址不能改变,必须初始化。   地址不可变::值可变

        int i = 5;int* const x = &i;        *x = 15;cout << *x << endl;         // output : 15        i = 25;cout << *x << endl;         // output : 25



4) 函数参数和返回值

   const 参数:    void fun1(const int i)
   void fun1(const int i)
    {
   i++;    // 错误  error C3892: 'i' : you cannot assign to a variable that is const
    }
           当以穿值方式向函数中传递参数时,会发生创建副本的情况,const也作为副本的一部分在函数中生效。


    但把这个过程呈现出来更好些,效果是一样的。
   void fun1(int i)
    {
   const int ic = i;
    }

            但函数接口如果是传引用或指针,如果不希望被修改最好还是用const。

   const 返回值:

       const 如果用于简单类型的返回值,并没有太大意义。 例如:
    const int fun2()
    {
   return 0;
    }


    用于用户自定义类型的比较有意义的。 例如:
        class X        {    int _i = 0;public:    X(int i):_i(i){};    void modify(){_i++;}};X func3(){return X();}const X func4(){return X();}void func5(X &x){x.modify();}void main(){    func3() = X(1);    func3().modify();    func5(func3());    func4() = X(1);    // 错误    func4().modify();  // 错误    func5(func4());    // 错误}

这里对于返回对象为const的是无法进行修改的,在实际应用中是有意义的。

如果传递的参数为指针或地址,如果不希望参数在函数执行过程中被改变,尽可能的用const进行修饰。


类中的const类型

    错误的使用

    class A    {    private:        const int _size=100;     // 非 static 的 const型无法在类中被初始化        int _arr[_size];         // 所以此处也无法确定数组的大小    public:        A(){};    };


    正确的使用

    class A    {    private:        const int _size;        int *_arr;    public:        A() : _size(100){_arr = new int[_size]};    };    class A    {    private:        enum {_size=100};        int _arr[_size];    public:        A(){};    };


   const 对象和成员函数

    有个对象,如果被定义为const,在应用的过程中,它的行为应该是怎样的?
    怎样保证 const 对象在调用它自身的成员函数时保证对象不会被改变?

    例如一个类 B
    class B    {    private:        int _i;    public:        B(int i): _i(i) {};        void add();        int const_add() const;    // const 成员函数        void show() const;        // const 成员函数    };    void B::add()  {  _i++;  }    void B::show() const    {  cout << _i << endl;  }    int B::const_add() const    {       //_i++;                    // 错误: 在const 成员函数中尝试改变对象的成员变量       return _i;    }    int main()    {        B b(2);        const B cb(4);        b.add();        b.const_add();        b.show();        cb.add();                 // 错误: cb 为 const 类型,不能通过cb的成员函数修改cb。        cb.const_add();        cb.show();        return 0;    }


    如何修改const 对象中的成员变量,使用关键字 mutable

    class Y    {        int _i;        mutable int _j;    public:        Y(){};        void addi() const;        void addj() const;    };    void Y::addi() {_i++;}       // 错误:  通过const 成员函数修改成员变量    void Y::addj() {_j++;}       // 正确:  _j 为mutable类型,可以跳过 const 限制    int main()    {        const Y cy;        cy.addi();        cy.addj();        return 0;    }



0 0
原创粉丝点击