【C++笔记】const作用

前往我的博客阅读体验更佳:本文链接

1. const定义变量

1.1 定义常量

由于常量定义后无法更改,所以定义时必须初始化!!!

1.2 类型检查

const常量编译时编译器会进行类型检查,#define宏定义只是字符串替换,没有安全检查,所以应该使用const定义常量。

1.3 extern

要使const变量在其他文件中访问,必须在文件中显式的指定为extern。

  • 未被const修饰的变量在不同文件的访问

    // file1.cpp
    int ext;
    
    // file2.cpp
    #include<iostream>
    extern int ext;
    int main() {
        std::cout << (ext + 10) << std::endl;
    }
    
  • 被const修饰的变量在不同文件的访问

    //extern_file1.cpp
    extern const int ext = 12;
    
    //extern_file2.cpp
    #include<iostream>
    extern const int ext;
    int main() {
        std::cout << ext << std::endl;
    }
    

    {% note success %}

    未被const修饰的变量不需要extern显式声明!而const常量需要显式声明extern,并且需要做初始化!

    {% endnote %}

2. 指针与const

与指针有关的const用法有如下四种:

const char *a1; //指向const对象的指针或者说指向常量的指针。
char const *a2; //同上
char *const a3 = NULL; //指向类型对象的const指针。或者说常指针、const指针。
const char *const a4 = NULL; //指向const对象的const指针。

{% note success %}

如果const位于*的左侧,则const就是用来修饰指针所指向的变量,即指针指向为常量
如果const位于*的右侧,则const就是修饰指针本身,即指针本身是常量

{% endnote %}

2.1 指向常量的指针

const int *ptr;
*ptr = 10; //error

该定义说明ptr指针是可变的,其所指向的对象是被const修饰,是常量,不可变。

非const对象的地址可以赋值给指向const对象的指针

int a = 101;
const int *p;
p = &a;      //ok
*p = 1;		 //error
std::cout<<*p<<std::endl;

p为一个指向const对象的指针,它可以指向非const对象a,但是不能通过p指针来修改a的值,可以通过其他方式修改,比如:

int a = 101;
const int *p;
p = &a;      		//ok
//*p = 1;           //error
std::cout << *p << std::endl;
int *p1 = &a;
*p1 = 102;     		//ok
std::cout << *p1 << std::endl;

2.2 常指针

int num = 0;
int *const ptr = &num; //const指针必须初始化!且const指针的值不能修改
cout << *ptr << endl;
int *t = &num;
*t = 1;
cout << *ptr << endl;

常指针必须初始化,且const指针的值不能修改。

可以通过非const指针更改const指针指向的值。

由于ptr指向的是一个变量,当把const变量的地址赋给ptr时会报错,如图

应该将ptr定义改为const int *ptrconst int * const ptr

3. 函数中使用const

3.1 const修饰函数返回值

跟const修饰普通变量和指针的含义相同。

  • const int

    const int func1();
    

    无意义,函数返回值就是赋值给其他变量。

  • const int*

    const int* func2();
    

    指针指向的内容不变。

  • int *const

    int *const func2();
    

    指针本身不可变。

3.2 const修饰函数参数

  • 传递过来的参数及指针本身在函数内不可变,无意义

    void func(const int var); // 传递过来的参数不可变
    void func(int *const var); // 指针本身不可变
    

    表明参数在函数体内不能被修改,但其实没有意义,因为var采用“值传递”,传入函数内部会复制到一个临时变量中,本身就不会被更改,传入的形参是指针也一样。

  • 参数指针所指内容为常量不可变

    若函数的功能需要返回多个值,在需要在函数参数中以地址传递的形式传入参数,但是输入参数不希望在函数内部被不小心更改,此时加入const修饰。

    void StringCopy(char *dst, const char *src);
    

    如上所示,dst是输出参数。src是输入参数,不希望更改,加上const修饰后,若在函数内部试图更改src所指向对象的内容,编译器将会报错。

  • 参数为引用,增加效率同时防止修改

    对于非内部数据类型的参数而言,像void func(A a)这样声明的函数注定效率比较低。因为函数体内将产生A类型的临时对象用于复制参数a,而临时对象的构造、复制、析构过程都将消耗时间。

    为了提高效率,可以将函数声明改为void func(A &a),因为“引用传递”仅借用参数的别名而已,不需要产生临时对象。

    但是“引用传递”有可能会更改参数的值,因此需要使用const进行修饰,即函数应该声明为void func(const A &a)

    由于内部数据类型的输入参数不存在构造、析构的过程,“值传递”和“引用传递”的效率几乎相当,不需要改写。

4. 类中使用const

4.1 const成员变量

对于类中的const成员变量必须通过初始化列表进行初始化,如下所示:

class Apple{
public:
    Apple(int i); 
    const int apple_number;
};

Apple::Apple(int i):apple_number(i)
{

}

若所有对象的常变量都一样,也可以利用下面方法初始化:

//.h文件
static const int apple_number;
//.cpp文件
const int Apple::apple_number = 10;

4.2 const成员函数

声明方式为正常函数声明+const,const在函数声明末尾,如下所示:

int getCount() const;

const对象只能访问const成员函数,而非const对象可以访问任何成员函数。

4.3 常对象

使用const修饰的对象,只能访问const成员函数。

//test1.cpp
class Apple {
private:
    int _weight;
public:
    Apple(int weight) {
        _weight = weight;
    };

    int getW();

    int getWeight() const;
};
//main.cpp
#include <iostream>
#include "test1.cpp"

using namespace std;

int main() {
    Apple a(2);
    const Apple b(3);
    a.getWeight();
    b.getWeight();
    a.getW();
    b.getW();//error
}

上述const对象b调用非const成员函数getW()报错。

本文为学习C++那些事 (github.com)所记笔记。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值