赞
踩
C++中const修饰的变量、指针及函数一直弄得似懂非懂,经常受其困扰。趁有时间对其做以整理归纳。
const 变量、指针及成员对象
const修饰的变量称之为常量,定义时必须为其赋值,且后续不能修改其值。
const修饰的指针分为两种:指针常量(int *const p)和指向常量的指针(int const *p 或 const int *p)。
const修饰的对象称之为常量成员对象,后续也不能修改其对象属性(内部私有变量),对于内置的数据类型,我们可以定义它们的常量,用户自定义的类也一样,可以定义它们的常量对象。
- /*************const 常量***********/
- int m = 10;
- const int n = 20; // 必须在定义的同时初始化
-
-
- /*************const 指针***********/
- const int *ptr1 = &m; // 指针指向的内容不可改变,但指针可以重新指向其它地址
- int * const ptr2 = &m; // 指针不可以指向其他的地方,但指针目前指向的地址中存放数据可以改变
-
- ptr1 = &n; // 正确
- ptr2 = &n; // 错误,ptr2不能指向其他地方
-
- *ptr1 = 3; // 错误,ptr1不能改变指针内容
- *ptr2 = 4; // 正确
-
- int *ptr3 = &n; // 错误,常量地址只能赋值给常量指针
- const int * ptr4 = &n; // 正确,常量地址初始化常量指针
-
- int * const ptr5; // 错误,指针常量定义时必须初始化
- ptr5 = &m; // 错误,指针常量不能在定义后赋值
-
- const int * const ptr6 = &m; // 指向“常量”的指针常量,具有常量指针和指针常量的特点,指针内容不能改变,也不能指向其他地方,定义同时要进行初始化
- *ptr6 = 5; // 错误,不能改变指针内容
- ptr6 = &n; // 错误,不能指向其他地方
-
- const int * ptr7; // 正确
- ptr7 = &m; // 正确,指向常量的指针可以指向普通变量
-
-
- /*************const 常量对象***********/
- class A{
- public:
- A(int i){ car = 0; }
- int getCar() const;
- void setCar(const int);
- ......
- private:
- int car;
- };
- const A a = new A(6); // 对象a为常量对象
const修饰函数参数及返回值
在函数入参为一个class结构对象时,为了提高效率,往往需要进行引用传递(类似于C中的指针传递),这样会省去产生临时对象的构造、析构的过程,同时为了避免修改原始对象,常用const修饰该引用。
- void Fun(A a); // 当调用Fun函数时,会创建临时对象a;在整个调用过程中会有构造、析构等过程,效率低下
-
- void Fun(const A &a); //为了更高效的调用,传入对象引用。但为了保证原始对象不被修改,常用const修饰
如果希望函数的返回值为const类型的对象地址时,那么该函数返回值可定义为const修饰的类型指针,该返回值只能被赋给加const 修饰的同类型指针。
- // 返回值为int类型的指针
- const int* GetValue();
-
- int *ptr = GetValue(); // 错误;
- const int *ptr = GetValue(); //正确;
如果返回值不是内部数据类型,返回值用对象的引用效率较高。但此时一定要小心,要搞清楚函数究竟是想返回一个对象的“拷贝”还是仅返回引用就可以了,否则程序会出错。
函数返回值采用“引用传递”的场合并不多,这种方式一般出现在类中对一些运算符的重载(重载=+,=,[ ] 等),结合另一篇博客中的string类实现:https://blog.csdn.net/ddazz0621/article/details/93981659。
const修饰成员函数
我们定义的类的成员函数中,常常有一些成员函数不改变类的数据成员,也就是说,这些函数是"只读"函数,而有一些函数要修改类数据成员的值。如果把不改变数据成员的函数都加上 const关键字进行标识,显然,可提高程序的可读性。其实,它还能提高程序的可靠性,已定义成const 的成员函数,一旦企图修改数据成员的值,则编译器按错误处理。
- class A{
- public:
- A(int i){ car = 0; }
- int getCar() const; //类的常量函数
- void setCar(const int);
- ......
- private:
- int car;
- };
常量成员对象不能调用非常量成员函数,因为它可能企图修改常量对象的数据成员。
构造函数和析构函数对这个规则例外,它们从不定义为常量成员,但可被常量对象调用(被自动调用)。它们也能给常量的数据成员赋值,除非数据成员本身是常量。
- // 非常量成员对象调用
- A objA = new A(6);
-
- objA.getCar(); // 正确
- objA.setCar(8); // 正确
-
- // 常量成员对象调用
- const A objB = new A(6);
-
- objB.getCar(); // 正确
- objB.setCar(8); // 错误;常量成员对象只能调用类的常量成员函数
以上为C++包含const修饰变量及函数的基本上所有的情况。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。