这里的T指的是一种数据类型,可以是int、long、doule等基本数据类型,也可以是自己类型的类型class。单独的一个const你肯定知道指的是一个常量,但const与其他类型联合起来的众多变化,你是不是就糊涂了?下面我们一一来解析。
const T
定义一个常量,声明的同时必须进行初始化。一旦声明,这个值将不能被改变。
1 | int i = 5; |
const T*
指向常量的指针,不能用于改变其所指向的对象的值。
1 | const int i = 5; |
const int* 与int* const的区别
指针本身就是一种对象,把指针定义为常量就是常量指针,也就是int* const的类型,也可以写成int *const,声明时必须初始化。
1 | int nValue = 10; |
const int* const 是一个指向常量对象的常量指针,即不可以改变指针本身的值,也不可以改变指针指向的对象。
1 | const int nConstValue1 = 5; |
const T&
对常量(const)的引用,又称为常量引用,常量引用不能修改其邦定的对象。
1 | int i = 5; |
允许为一个常量引用邦定一个非常量对象、字面值,甚至是表达式;引用的类型与引用所指向的类型必须一致。
1 | int i = 5; |
const T*&与T *const&
指向常量对象的指针的引用,这可以分两步来理解:1.const T是指向常量的指针;2.const T&指向常量的指针的引用。
1 | const int nConstValue = 1; //常量对象 |
在函数中的应用
我们直接从需求出来,假设有这样一个数据结构:
1 | typedef struct __Data |
1.希望传入一个对象,又不想让函数体修改这个对象。
方式<1>
1 | void Dealwith(const Data& data) |
方式<2>
1 | void Dealwith(const Data* pData) |
这种方式与void Dealwith(const Data& data)的功能相同
方式<3>
1 | Data g_data(20); |
调用如下:
1 | Data d(10); |
这种方式函数未改变传入的对象的值,但可以返回另外一个对象的指针。注意返回的指针必须指向全局的对象,如果返回函数内定义的对象,退出函数作用域后,其指针将无效,这是非常危险的;如果Dealwith是成员函数,也可以返回指向成员的指针。
2.在类中的使用,返回一个类的成员,但不希望调用方修改这个成员。
方式<1>
1 | class MyData |
调用如下:
1 | MyData mydata("", Data(100)); |
方式<2>
有人可能会问GetData也可以写成这样:
1 | const Data& GetData() |
这样的话,调用方常常容易写成这样:
1 | MyData mydata("", Data(100)); |
这样调用时会有一个结果赋值的过程,如果Data是一个复杂的类,会有较大的开销,其效果与下面这种方式是一样的:
1 | Data GetData() |
当然,如果调用方这样使用是正确的:
1 | const Data& GetData() |
这对调用方的技术能力要求比较高,如果你是设计方,一定要尽量使接口简单易用。
方式<3>
如果你要传入一个Data进行一些处理,处理完后返回类的成员m_data,可如下实现:
1 | void DoSomething(const Data*& pData) |