const 使用小结
is2120@csdn
1. 修饰变量,使得在初始化变量值后不能在修改其值。
// 无const修饰
int x = 4;
x = 10;
// 有const修饰
const int x = 2;
x = 10; // err
2. const替代#define的好处
在调试时可以看见变量名,而#define后调试时只能看见值
避免了宏定义带来的种种麻烦(宏是直接的文本替代,这会带来问题)
3. const 和指针
const int x; // constant int
x = 2; //x 非法--不能修改x
const int* pX; // 一个指向const int的指针,指针值可变
*pX = 3; //x 不能使用px修改一个const int的值
pX = &someOtherIntVar; // 但是px可以指向其他的地方
int* const pY; // 指针为const,其所指向的值类型为int
*pY = 4; // 使用pY修改int的值
pY = &someOtherIntVar; //x 不能指向其他地方
const int* const pZ; // const指针,指向const变量
*pZ = 5; //x
pZ = &someOtherIntVar; //x
4. const、指针和类型转换
int y;
//z 此处const的含义是:并不是说指向的变量必须是const,而是说你不能使用该指针来变更其指向的值
const int* pConstY = &y; //x 不能使用pConstY来修改y
int* pMutableY = &y; //x 能使用pMutableY来修改y
*pMutableY = 42;
5. c++中不允许轻易绕过const属性
赋值操作符不能没有经过明确的抓换而将一个const int * 转换成int *
c++不支持将一个const type 类型的变量转换成为type类型的标准转换。
const int x; // x不可修改
const int* pX = &x;
*pX = 4; //x 错误
int* pInt; // 一般类型的指针(非const)
pInt = pX; //x 错误,不能将一个const int * 指针转换成为 int *
int *pInt; //
pInt = &x; // 错误,不能将const int* 转换成 int *
6. 强制编译器进行类型转换(const type -> type)
const int x = 4;
const int* pX = &x;
cout << x << endl;
// 强制将 px 由 const int* 转换成 int *
int* pX2 = (int *)pX;
*pX2 = 3; //错--结果是未定义的(UB)
cout << x << endl; //
上述代码在vc中所产生的会变代码
ASSEMBLER OUTPUT C++ CODE
Mov eax, DWORD PTR _pX$[ebp] int* pX2 = (int *)pX;
Mov DWORD PTR _pXX$[ebp], eax
Mov eax, DWORD PTR _pXX$[ebp] *pX2 = 3;
Mov DWORD PTR [eax], 3
Push OFFSET FLAT:?endl@@......... cout << x << endl;
Push 4
注意到这里的PUSH 4,即编译器觉得你定义了一个const变量,在使用的时候就没有解引用而直接引用其值了(优化的结果)。
7. const_cast 操作符
使用 const_cast 去除变量的常量性。
const int x = 4; //
const int* pX = &x; //
cout << x << endl; // prints "4"
int* pX2 = const_cast < int* > (pX); // 将pX显式转换成非const
*pX2 = 3; // 未定义(BH)
cout << x << endl; //
同c style的强制类型转换不同的是,const_cast 只会改变变量的常量性,而不会改变变量的类型。
8. const 存储与字符常量
char* szMyString = "Hello world."; // 定义了一个字符常量
szMyString[3] = 'q'; // 未定义,试图修改静态缓冲区
标准认为这些字符常量的类型是const,一个字符常量的类型是一个const chars的数组。
c++中不能将一个const type标准转换为 type 类型。
const char constArray[] = { 'H', 'e', 'l', 'l', 'o', '/0' };
char nonConstArray[] = { 'H', 'e', 'l', 'l', 'o', '/0' };
char* pArray = constArray; // illegal
char* pArray = nonConstArray; // legal
但是这样又是可以的
// should be illegal - converts array of 6 const char to char*
char* pArray = "Hello";
这是为了和旧式的c代码兼容
9. 同样的字符常量可能指向同一个内存区域
"The /GF option causes the compiler to pool strings and place them in read-only memory.
例如以下代码
#include <stdio.h>
int main()
{
char* szFirst = "Literal String";
char* szSecond = "Literal String";
szFirst[3] = 'q';
printf("szFirst (%s) is at %d, szSecond (%s) is at %d/n",
szFirst, szFirst, szSecond, szSecond);
return 0;
}
在启用“string pooling”后,其输出为
szFirst (Litqral String) is at 4266616, szSecond (Litqral String) is at 4266616
(我这里是运行错误)
10. 总是使用 const
class Person
{
public:
Person(char* szNewName)
{
// make a copy of the string
m_szName = _strdup(szNewName);
};
~Person() { delete[] m_szName; };
const char* const GetName() const
{
return m_szName;
};
private:
char* m_szName;
};
在返回指针、使用指针作为参数时,总是想想是否适用const。
这样会使得编程变得比较轻松。
11. const 成员函数
const成员函数:该函数不会修改函数成员并且不会调用非const成员函数。
const 或者 non-const 对象都可以调用 const 成员函数
const对象不能调用non-const成员函数
12. The Mutable Storage Specifier
A mutable member variable can be modified even by const member functions.
即便是一个const 成员函数也能修改一个 mutable 成员变量。
class MyData
{
public:
/*
the first time, do calculation, cache result in m_lCache, and set
m_bCacheValid to true. In subsequent calls, if m_bCacheValid is true
then return m_lCache instead of recalculating
*/
long ExpensiveCalculation() const
{
if (false == m_bCacheValid)
{
m_bCacheValid = true;
m_lCache = ::SomeFormula(m_internalData);
}
return m_lCache;
};
// change data and set m_bCacheValid to false to force recalc next time
void ChangeData()
{
};
private:
data m_internalData;
mutable long m_lCache;
mutable bool m_bCacheValid;
};
is2120@csdn
@IS2120#CNBLOGS.T2169364049[T1,L65,R1,V259]:备忘
$ € ₤ ₭ ₪ ₩ ₮ ₦ ₱ ฿ ₡ ₫ ﷼ ¥ ﷼ ₫ ₡ ฿ ₱ ₦ ₮ ₩ ₪ ₭ ₤ € $