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

 

posted @ 2018-01-06 14:18  子非也  阅读(287)  评论(0编辑  收藏  举报