C++ const
1.const 修饰变量
int base = 0; // 定义常量(类中的只读变量 只能且必须 在初始化列表中initialize) // const常量只是给出了对应的内存地址,而不是像#define一样给出的是立即数,所以const定义的常量 // 在程序运行过程中只有一份拷贝,而#define定义的常量在内存中有若干个拷贝。 const int a1 = 1; // 编译器可以对它进行类型安全检查(宏常量只是简单的替换,可能会产生意料不到的错误) int const a2 = 1; // 修饰指针 int * const b1 = &base; // 同时修饰值和指针 int const * const c1 = &base; const int * const c2 = &base; // const修饰记忆:限定关键字左边的,本身在最左边时限定右边
2.const 修饰函数(参数、返回值、函数本身)
class Code { CString m_code; public: Code() {} ~Code() {} const CString* getCode(const CString& src)const; void setCode(const CString& src); };
void Code::setCode(const CString& src) { m_code = src; } const CString* Code::getCode(const CString& src) const { // error //src = result; // const修饰的变量只读,且在只读函数内 //m_code = src; // const修饰的类成员函数 不能修改成员 //setCode(src); // const修饰的类成员函数 只能调用只读成员函数 return &m_code; }
getCode()函数的返回值必须用 const CString* re = code.getCode( _T("GB1001") ); 或者写成 auto re = code.getCode( _T("GB1001") );
这种只读的保证是编译器做的限制,少数情况下要在只读函数内修改对象的属性,可以这么做:
const CString* Code::getCode(const CString& src) const { // 1.mutable关键字修饰 mutable int value; // 2.绕过编译器的限制 Code* p = (Code*)this; // 关键在于this强转为Code* p->setCode(src); return &m_code; }
const和函数重载
void Code::fun(int a)const // 可以重载,根据对象是否只读区别 {} void Code::fun(int a) {} void Code::f(const int a) // 无法重载 {} void Code::f(int a) {}
3.const修饰对象
const修饰的对象只能访问 类中的只读函数,不能修改变量。较好的设计应该是用const限定方法,不限定对象,类中的属性只能通过方法 Get() 或 Set() .
const和智能指针
CString name(_T("")); shared_ptr<Code> pCode1(new Code(name)); // const只能限定包在数据类型外面的Ptr只读,所以 Get( const shared_ptr<Code> code)并不能限制到code对象 const shared_ptr<Code> pCode2(new Code(name)); pCode2->setCode("GB1001"); //pCode2 = pCode1; // error 该智能指针只读
4.只读迭代器
5.const 在C语言和C++中的不同
C++中的const一般被看成编译期的常量,不为const分配空间, 只是在编译的时候将值保存在符号表中,并在适当的时候折合在代码中
C++中, 是否为const分配空间要看具体情况,若加上关键字extern或者取const变量地址,编译器就要为const分配存储空间
C语言中的const是一个不能被改变的普通变量,会占用存储空间
const int size = 10; int array[size] = { 0 }; // C语言中error: 编译器不知道编译时的值(数组下标必须明确)
6.const_cast 关键字
// const_cast用来移除变量的const或volatile限定符: // 使用const_cast再写的后果是未定义的,const_cast的目的并不是为了让你去修改一个本身被定义为const的值, // 因为这样做的后果是无法预期的。const_cast的目的是修改一些指针/引用的权限, // 如果我们原本无法通过这些指针/引用修改某块内存的值,现在你可以了。 const int a = 1; //int* temp = a; // error int* pa1 = const_cast<int*>(&a); // 去除const限制 int* pa2 = (int*)&a; // 传统方式去除const限定 *pa1 = 10; int modify1 = a; // 1,这里直接被替换成常量表达式,不再从地址中取值(const常量引入的初衷是替代#define常量) *pa2 = 100; int modify2 = a; // 1