1. const 修饰成员变量
使用 const 修饰常见类型时,就是代表这个参数是常量,不可以修改的。
例如:
const int num1 = 1;
//num1 = 2; //这种尝试修改num1的语句就会报错
当用其修饰指针的时候,有两种情况:
const修饰符在 * 号左边时,这代表的是该指针指向的变量是不可修改的,但是指针指向的地址时可以修改的。
例如:
int num1 = 5;
const int* ptr1 = &num1;
const int* ptr2 = &num1;
ptr1 = ptr2; //合法
//*ptr1 = 1; //不合法
const修饰符在 * 号右边时,这代表了该指针指向的地址是不可改变的,但是该指针指向的变量是可以改变的。
例如:
int num1 = 5;
int* const ptr3 = &num1;
int* const ptr4 = &num1;
//ptr3 = ptr4; //不合法
*ptr3 = 1; //合法
const修饰符在 * 号两边时,代表了这个指针既不能修改指向的地址,也不能修改指向变量的值。
2. const 修饰函数参数
修饰函数参数时,若参数是不是引用或指针时,代表的是该参数在函数内部不允许修改。当参数是引用或指针时,代表的是该指针或引用的对象不允许修改。
例如:
void const_test(const int num) {
//num = 3; //不合法
}
void const_test2(const int& num) {
//num = 3; //不合法
}
其中参数需要使用 const 修饰参数从而保护参数不被修改的只有当参数是引用或指针的时候。
因为若是按值传参的话只是将参数的副本传入了函数内部,在函数内部做任何修改都不会影响到参数。数据非常安全,用不上 const 修饰符
另外两种传参方式,引用传参和指针传参的好处在于,他不需要生成参数的副本,只是传入了一个地址,效率高。但是他有修改参数的风险,所以这时候就需要 const 修饰符对数据进行保护了。
总结
当使用 const 修饰函数参数时,最常用的用法就是参数为自定义类型时,使用 void func(const T& t) 来进行传参,这样效率最高而且安全。
对于内部数据类型使用按值传参和引用传参是同等效率的,所以没有必要使用 void func(const int t) 这种方式传参。
3. const 修饰函数返回值
其实修饰函数返回值和修饰函数参数,基本上是同一用处,对于非指针类型基本没有效果。只有当返回值是指针时,通过使用 const 修饰符来表示该返回值是不可修改的。
需要注意的是,如果给指针传参方式的函数返回值加
const修饰,那么函数返回值(即指针)的内容不能被修改,该返回值只能被赋给加const修饰的同类型指针。
例如:
const int* get_num();
//int* num = get_num(); //不合法
const int* num = get_num(); //用于接收返回值的指针类型必须是const
其实这种最常用的就是返回自定义类型的引用时使用 const 进行保护,提高传递效率。
例如:
const T& get_T();
4. const 修饰函数
使用 const 修饰函数就是声明该函数不会修改成员变量的值。
声明方法如下:
void func() const;
通常用于定义类的成员函数时声明该函数不会改变成员变量的值,从而可以在当该类的实例化作为 const 修饰的一个引用参数时,可以调用其方法。
例如:
class Myclass {
public:
int value;
int get_value1() { return this->value; }
int get_value2() const { return this->value; }
};
const Myclass& get_max(const Myclass& cla1, const Myclass& cla2) {
//if (cla1.get_value1() < cla2.get_value1()) //若想调用get_value1则会报错
if (cla1.get_value2() < cla2.get_value2())
return cla2;
return cla1;
}
可以发现,即使 get_value1() 没有修改任何成员变量的值,但是还是不能够调用。因为他没有使用 const 声明。只有使用了 const 声明的 get_value2() 是可以在这种情况下调用的。