C++ const

目的: 值代替。 

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


      

内存存储形式,常量折叠

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

下面的程序可以说明。 

    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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值