• C++ const小结


    const是C++的精髓。用法很多,学会善用const非常非常重要。

    const变量

    const可用于修饰变量,表示这个变量不可修改:

    const double pi = 3.14;
    // double const pi = 3.14; 等效的(const放在前后都可以)
    

    这样一来,x就成为编译器眼里的常量,如果尝试给它赋值编译器就报错。这样后面用到很多次需要修改时,就只用改一个了。它的语义通常是“这个变量是整个程序的全局属性,放在开头方便修改”。

    喜欢违背规则是人的本性。如果我非要修改它怎么办?那我可以把他的地址取出来强行修改:

    const int a = 3; // 1
    
    main() {
    	static const int a = 3; // 2
    	const int a = 3; // 3
    	int *p = (int *)(&a); //获取a的地址,强行转换修改
    	cout << *p << endl;
    
    	*p = 9;
    	cout << "modifyed\n";
    	cout << *p << endl;
    }
    

    测试发现,情况1和2会报错,3则正常运行。这是因为1和2中a定义为const后编译时就被放到了只读区,在运行时无权限修改;而情况3下a成为一个栈变量,所以运行时跟其他变量没区别,不会有限制,仅仅是编译器不让你直接改而已。

    以上这些都是作死取常量地址导致的,如果没有取地址又开了些优化的话,编译时有可能并不生成a,而是像define一样直接替换后文。这样时间上会更快,但空间上往往会更大。

    const指针与传参

    下面再看看const作用到指针和引用的情况

    int n = 3;
    const int cn = 3;
    
    const int &nn = n;
    // int &nn = cn;
    
    int *const p = &n;
    const int *p = &n;
    

    引用很简单,跟普通变量没有区别。nn不能赋值(但可以给n赋值一起改变两个),但cn不能绑定给nn,因为const赋值给别人时只能继续加不能消除,不然一个引用就可以去掉常量属性了。

    在看指针,指针的*好像有很多拜访方式,但其实就两类:

    • const在*左侧,此时p可以修改,但*p不能修改
    • const在*右侧,此时*p可以修改,但p不能修改,和引用一样,const数不能赋值给这种能修改的指针

    多重指针const的通用规则

    以二级指针为例,对于多重指针来说也一样。

    image

    const与成员函数

    const的另一个重要用途就是修饰成员函数。给一个函数加上const,表示该对象成员不可被修改:

    struct A{
    	int a;
    	void foo() const {
    		//a = 6; 错误!不可修改
    	}
    };
    

    这种方式好处多多,它的语义即“该函数不修改对象”,让编译器来检查,也方便阅读。

    const成员函数的重载

    在C++中,两个成员函数如果一个有const另一个没有,那么他们是可以重载的。

    class TextBlock{
    public:
    	const char& operator[](int pos) const {return text[pos];}
    	char& operator[](int pos) {return text[pos];}
    };
    

    这个重载的意义是什么呢?因为const对象只能调用const函数,所以这样一来,const对象会调用第一个(仅能读),其他对象会调用第二个(支持读写)。

    constexpr(C++11)

    constexpr关键字是C++11新加入了关键字。用于在某些情况下替代const。在传统C++里,const修饰的量分为两种:编译时常量和运行时常量:

    const int a = 5;//编译时常量
    void f(int t) {
    	const int p = t; //运行时常量
    }
    

    显然,编译时常量就是可以在编译器确定值的,反之则是直到运行才能确认,对他们的处理策略是大不相同的。但是有些时候不好判断你的const是那一种,所以constexpr就成为了手动区分他们的工具。

    上例中,将a修改为constexpr,通过编译,验证说明a是编译时常量(因为5是);修改b时则报错,说明b不是编译时常量(因为t不是)。

    constexpr还可作用给函数:

    constexpr int size() {
    	return 42;
    }
    constexpr int scale5(int x) {
    	return 5 * x;
    }
    constexpr int a = scale5(4);
    constexpr int b = size();
    // constexpr int c = scale5(i);
    

    这样一个函数必须要短小(只能有一条return语句)。如果参数为常量表达式(scale5(4)),那么返回值也为常量。否则会被当做一般函数处理,所以c的赋值是错误的,即constexpr函数不一定返回常量值。

    注:这是C++11中的constexpr内容,在后续版本中,constexpr的用法又有了较大的修改。

    const会提高效率吗

    读一个只读变量和读写变量,没有理由存在效率上的差异。但是在编译的层面上,有意添加const可以为编译器提供更多信息,指示编译器更加大胆的优化(就好比volatile或者restrict一样),所以在特定情况下可以生成更优秀的汇编码,跑得更快。

  • 相关阅读:
    Python+selenium常见报错
    jmeter压力测试指标解释
    jemte自动生成测试报告方法
    iview清空Date-picker组件后请求报错解决方法
    【求助】Django+vue项目时候遇到一个问题,table的data数据怎么更新
    django_数据库操作—增、删、改、查
    django-关于manage.py migrate无效的问题
    python家里的环境和公司环境怎么同步
    python class类的属性应用及init初始化实践 ---勇者斗恶龙
    IDLE与pycharm执行相同代码结果却不同,原因分析
  • 原文地址:https://www.cnblogs.com/ofnoname/p/16466468.html
Copyright © 2020-2023  润新知