C++ Const关键字

Const关键字

const 是constant 的缩写,本意是不变的,不易改变的意思。在 C++ 中是用来修饰内置类型变量,自定义对象,成员函数,返回值,函数参数。

1.用const修饰成员变量

  • 普通变量
    const 常量,只能赋值一次。
const int num = 111;//合法
num = 222;//报错,不能给常量赋值
  • 指针变量
    只有一个const时,如果const位于*的左侧,表示指针所指的数据是常量,不能通过该指针修改实际数据,指针本身是变量,可以指向其他内存单元。
int num1 = 123;
int num2 = 456;
const int * ptr_num1 = &num1;
int const * ptr_num2 = &num1;
ptr_num1 = &num2;//合法
*ptr_num1 = 789;//报错,不能给常量赋值

只有一个const时,如果const位于*的右侧,表示指针本身是常量,不能指向其他内存单元,指针所指的数据可以修改。

int num1 = 123;
int* const ptr_num1 = &num1;
*ptr_num1 = 456;//合法
ptr_num1 = &num2;//报错,不能给常量赋值

有两个const,位于*左右两侧,表示指针本身和指针所指向的数据都是常量,不能修改。

int num1 = 123;
int num2 = 456;
const int* const ptr_num = &num1;
ptr_num = &num2;//报错,不能给常量赋值
*ptr_num = num2;//报错,不能给常量赋值

2.用const修饰函数的参数

如果参数是作输出用的,那么不论它是什么数据类型,也不论它采用“指针传递”还是“引用传递”,都不能加const 修饰,否则该参数将失去输出功能。所以const 只能修饰输入参数。

  • 输入参数采用“指针传递”
    加const 修饰可以防止意外地改动该指针,起到保护作用
void StringCopy(char* strA, const char* strB)
{
    //指针对象strA可以修改
}
  • 输入参数采用“值传递”
    值传递,传递的是实际参数的一个副本,此时加const与修饰变量时的性质一致
//内置数据类型
void TestFun1(const int value)
{
    value = 123;//报错,不能给常量赋值
}
//非内置数据类型,A 为用户自定义的数据类型
void TestFun2(const A a)
{
    a = A();//报错
}

由于函数将自动产生临时变量用于复制该参数,该输入参数无需保护,所以一般不加const 修饰。所以上述函数一般写作如下:

void TestFun1(int value);
void TestFun2(A a);
  • 输入参数采用“引用传递”
    对于非内部数据类型的参数而言,例如:void TestFun2(A a) 这样声明的函数效率比较低。因为函数体内将产生A 类型的临时复制对象,而临时对象的构造、复制、析构过程都将消耗时间。为了提高效率,可以将函数声明改为void TestFun3(A& a),因为引用传递,对形参的操作等同于对实参的操作,即传递的不会是实参的副本,而就是实参,只是起了个别名而已。
void TestFun3(const A& a)
{
    //此时无法修改a对象及其任何成员变量,也不能调用非const修饰的函数
}

3.用const修饰函数的返回值

  • 返回值采用“指针传递”
    那么函数返回值(即指针)的内容不能被修改,该返回值只能被赋给加const 修饰的同类型指针。
const int * TestFun4(int& num)
{
 	return #   
}

int num = 15;
int * ptr_num = TestFun4(num);//报错,无法从“const int *”转换为“int *”
const int * ptr_num = TestFun4(num);//正确使用方式
  • 返回值采用“值传递”
    由于函数会把返回值复制到外部临时的存储单元中,此时加const 修饰没有任何价值。
const int TestFun5();
const A TestFun6();//A 为用户自定义的数据类型
//所以上面的函数写法一般改写成下面的写法
int TestFun5();
A TestFun6();//A 为用户自定义的数据类型
  • 返回值采用“引用传递”
    如果返回值不是内部数据类型,那么为了提升效率,可以将函数A TestFun6() 改写为const A & TestFun6()。但是值得注意的是,此时一定要搞清楚函数究竟是想返回一个对象的“拷贝”还是仅返回“别名”就可以了。如果函数可以返回对象,也可以返回对象的引用,应该首选对象的引用,因为这样效率高。
const A & TestFun7(A & a)
{
    return a;
}
//如果函数要返回局部对象,就应该直接返回这个对象,不应该采用返回对象的引用
const A & TestFun8()//错误使用方式
{
    A a;
    return a;
}

4.用const修饰成员函数

任何不会修改数据成员的函数都应该声明为const 类型。

class TestClass
{
    public:
        int value;
        int GetValue() const { return value; }//正确使用方式
        void ModifyValue() const
        {
            value = 123;//报错,由于正在通过常量对象访问“value”,因此无法对其进行修改
        }
}

注意:const 关键字不能与 static 关键字同时使用,因为 static 关键字修饰静态成员函数,静态成员函数不含有 this 指针,即不能实例化,const 成员函数必须具体到某一实例。
使用mutable和volatile关键字修改的变量可以突破const限制。C++中的mutable和volatile

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值