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

posted @ 2011-03-19 22:31  BiG5  阅读(169)  评论(0编辑  收藏  举报