const
const
的使用constant
const int MAX_N = 1e3;
// =
// int const MAX_N = 1e3;
// 含义:const 修饰的类型为 int 的变量 MAX_N 的值不可变
pointer
#include <iostream>
using namespace std;
int n1 = 1, n2 = 2;
int* const p1 = &n1; // 指针不可变,指向内容可以变
const int* p2 = &n1; // 指针可以变,指向内容不可变
const int* const p3 = &n1; // 指针不可变,指向内容不可变
int main() {
cout << "&n1:\t" << &n1 << "\t n1:\t" << n1 << endl;
cout << " p1:\t" << p1 << "\t*p1:\t" << *p1 << endl;
cout << " p2:\t" << p2 << "\t*p2:\t" << *p2 << endl;
*p1 = 2;
// p1 = &n2;
cout << "&n1:\t" << &n1 << "\t n1:\t" << n1 << endl;
cout << " p1:\t" << p1 << "\t*p1:\t" << *p1 << endl;
cout << " p2:\t" << p2 << "\t*p2:\t" << *p2 << endl;
// &n1: 004F4038 n1: 1
// p1: 004F4038 *p1: 1
// p2: 004F4038 *p2: 1
// &n1: 004F4038 n1: 2
// p1: 004F4038 *p1: 2
// p2: 004F4038 *p2: 2
return 0;
}
#include <iostream>
using namespace std;
int n1 = 1, n2 = 2;
int* const p1 = &n1; // 指针不可变,指向内容可以变
const int* p2 = &n1; // 指针可以变,指向内容不可变
const int* const p3 = &n1; // 指针不可变,指向内容不可变
int main() {
cout << "&n1:\t" << &n1 << "\t n1:\t" << n1 << endl;
cout << " p1:\t" << p1 << "\t*p1:\t" << *p1 << endl;
cout << " p2:\t" << p2 << "\t*p2:\t" << *p2 << endl;
// *p2 = 2;
p2 = &n2;
cout << "&n1:\t" << &n1 << "\t n1:\t" << n1 << endl;
cout << " p1:\t" << p1 << "\t*p1:\t" << *p1 << endl;
cout << " p2:\t" << p2 << "\t*p2:\t" << *p2 << endl;
// &n1: 008F4038 n1: 1
// p1: 008F4038 *p1: 1
// p2: 008F4038 *p2: 1
// &n1: 008F4038 n1: 1
// p1: 008F4038 *p1: 1
// p2: 008F403C *p2: 2
return 0;
}
function
// const 修饰函数参数
// 传递过来的参数在函数内不可以改变(无意义,因为 Var 本身就是形参)
void function(const int Var);
// 参数指针所指内容为常量不可变
void function(const char* Var);
// 参数指针本身为常量不可变(也无意义,因为 char* Var 也是形参)
void function(char* const Var);
// 参数为引用,为了增加效率同时防止修改
// 这样的 const 引用传递和最普通的函数按值传递的效果是一模一样的,禁止对引用的对象的一切修改
// 唯一不同的是按值传递会先建立一个类对象的副本,,然后传递过去
// 而它直接传递地址, 所以这种传递比按值传递更有效
void function(const int& Var); // 引用参数在函数内为常量不可变
class
#include<iostream>
using namespace std;
class Test {
protected:
int data;
public:
void fun1();
void fun1() const; // 上一函数的重载
void fun2();
void fun3() const;
};
void Test::fun1() {
cout << "fun1() called " << endl;
}
void Test::fun1() const { // const 是函数类型的一部分,实现部分也要带该关键字
// data = 1; // 常成员函数不能更新类的成员变量
// fun2(); // 常成员函数不能调用该类中的非常成员函数,只能调用常成员函数。
cout << "fun1() const called " << endl;
}
void Test::fun2() {
cout << "fun2() called " << endl;
}
void Test::fun3() const {
cout << "fun3() const called " << endl;
}
int main() {
Test test1 = Test();
const Test test2 = Test();
test1.fun1(); // fun1() called
test2.fun1(); // fun1() const called
// 非常量对象也可以调用常成员函数,但是如果有重载的非常成员函数则会调用非常成员函数。
test1.fun1(); // fun1() called
test1.fun3(); // fun3() const called
return 0;
}
const
的作用保护修饰内容
函数重载
类型检查
const
常量有数据类型,而宏常量没有数据类型。编译器可以对前者进行类型安全检查,而对后者只进行字符替换,没有类型安全检查,并且在字符替换时可能会产生意料不到的错误。
可以节省空间,避免不必要的内存分配
// const 定义常量只给出了对应的内存地址
// #define 给出的是立即数
// 所以 const 定义的常量在程序运行过程中只有一份拷贝
// 而 #define 定义的常量在内存中有若干个拷贝
#define p1 3.14159 // 宏常量
const double p2 = 3.14159; // 此时并未分配内存
double d1 = p1; // 编译期间进行宏替换,分配内存
double d1 = p2; // 此时为 p2 分配内存,以后不再分配!
double d1 = p1; // 再进行宏替换,又一次分配内存!
double d1 = p2; // 没有内存分配
提高效率
编译译器通常不为普通 const 常量分配存储空间,而是将它们保存在符号表中,这使得它成为一个编译期间的常量,没有了存储与读内存的操作,效率很高
const
的使用建议const
类型;const
应该使用引用或指针,而不是一般的对象实例;const
;const
引用。