- const 修饰普通变量
- const修饰指针变量
- const修饰普通函数的值传递参数、引用&指针传递参数、返回值
- const修饰类成员函数
const int Max=100;
const常量有数据类型,而宏常量没有数据类型。编译器可以对前者进行类型安全检查,而对后者只进行字符替换,没有类型安全检查,并且在字符替换时可能会产生意料不到的错误。
void f(const int i)
{
.........
}
//对传入的参数进行类型检查,不匹配进行提示
防止意外的修改,增强程序的健壮性。
void f(const int i)
{
i=10;//error!
}
//如果在函数体内修改了i,编译器就会报错
同宏定义一样,可以做到不变则已,一变都变。
class A
{
public:
void f(int i){......} //一个函数
void f(int i) const {......} //上一个函数的重载
};
const定义常量从汇编的角度来看,只是给出了对应的内存地址,而不是象#define一样给出的是立即数,所以,const定义的常量在程序运行过程中只有一份拷贝,而#define定义的常量在内存中有若干个拷贝
#define Pi 3.14159 //常量宏
double a=pi; //编译期间进行宏替换,分配内存
double b=Pi; //再进行宏替换,又一次分配内存!
......
const doulbe Pi=3.14159; //此时并未将Pi放入ROM中
double a=Pi; //此时为Pi分配内存,以后不再分配!
double b=Pi; //没有内存分配
编译器通常不为普通const常量分配存储空间,而是将它们保存在符号表中,这使得它成为一个编译期间的常量,没有了存储与读内存的操作,使得它的效率也很高。
const修饰普通类型的变量被赋值后,其值不允许被修改。
const int a = 7;
a = 8; // 错误,a 被编译器认为是一个常量,其值不允许修改。
1.如果const位于 * 的左侧,const 修饰指针指向的内容,则内容为不可变量,简称左定值;
int a = 7;
int b = 8;
const int* c = &a;
*c = b; //错误:指针指向的内容不可修改
c = &b;//正确:指针可以修改
2.如果const位于*的右侧,const 修饰指针,则指针为不可变量,简称右定向;
int a = 7;
int b = 8;
int* const c = &a;
*c = b; //正确:指针指向的内容可修改
c = &b;//错误:指针为不可变量
3.const 修饰指针和指针指向的内容,则指针和指针指向的内容都为不可变量。
int a = 7;
int b = 8;
const int* const c = &a;
*c = b;//错误:指针指向的内容不可修改
c = &b;//错误:指针为不可变量
“左定值,右定向,const修饰不变量”。
1、const传递参数
void func(const int p)
{
cout << "p = " << p << endl;
++p;//错误:p值不能修改
}
int main()
{
int a = 10;
int b = 20;
func(a);
func(b);
return 0;
}
#include
using namespace std;
int b = 30;
void func(int* const p)
{
cout << "*p = " << *p << endl;
++*p;//正确,p指向的值可以修改
p = &b;//错误:p不能被修改
}
int main()
{
int a = 10;
func(&a);
cout << "a = " << a << endl;
return 0;
}
/*定义一个学生类,获取学号*/
class Student
{
public:
Student(){}//默认构造函数
Student(int num):number(num){}//初始化列表
int get_number() const //const修饰成员函数,不可修改被调用对象的值
{
return number;
}
int set_number(int num);
private:
int number;
};
//普通函数
void get_student_number(const Student& stu)//避免了临时对象构造
{
cout<<stu.get_number()<<endl;
stu.set_number(3333);//错误!对象stu不能被修改
}
int Student::set_number(int num)
{
this->number = num;
return this->number;
}
int main(void)
{
Student RF(1001);
get_student_number(RF);
int rf_num = RF.set_number(2222);
cout << "rf_num = " << rf_num << endl;
return 0;
}
2、const 修饰函数的返回值【用的少,有机会用到再补充】
const 修饰自定义类型的作为返回值,此时返回的值不能作为左值使用,既不能被赋值,也不能被修改。
const 修饰返回的指针或者引用,是否返回一个指向 const 的指针,取决于我们想让用户干什么。
const Screen blankScreen;
blankScreen.display(); // 对象的读操作
blankScreen.set(‘*’); // 错误:const类对象不允许修改
class Screen {
public:
char get() const;
};
char Screen::get() const {
return _screen[_cursor];
}
class Screen {
public:
int ok() const {return _cursor; }//读可以
int error(intival) const { _cursor = ival; }//修改不行!
};
class Name {
public:
void setName(const string &s) const;
private:
char *m_sName;
};
void setName(const string &s) const {
m_sName = s.c_str(); // 错误!不能修改m_sName;
for (int i = 0; i < s.size(); ++i)
m_sName[i] = s[i]; // 不好的风格,但不是错误的
//虽然 m_Name 不能被修改,但 m_sName 是 char * 类型,const 成员函数可以修改其所指向的字符。
}
class Screen {
public:
char get(int x,int y);
char get(int x,int y) const;
};
//在这种情况下,类对象的常量性决定调用哪个函数。
const Screen cs;
Screen cc2;
char ch = cs.get(0, 0); // 调用const成员函数
ch = cs2.get(0, 0); // 调用非const成员函数