C++基本功:全面掌握const、volatile和mutable关键字

   C++ 程式设计过程中 ,const 的使用可以频度是非常高的 . 它在保证程式安全方面起到了不可估量的作用 .
用一句话来表达最确切不过了:”小兵立大功” .
   有了 const, 那么 mutable 当然缺不了 .
   然作为 const 的同胞兄弟 ,volatile 却在很多人的视野中消失 . 其实 volatile 担负的责任有何尝小呢 ?
   自然 , 它们的用法多样而灵巧 , 以至新手迷惑久久 , 下面就来系统的探讨总结一下吧:

一 . 一般应用 
1.const 修饰各种变量的用法 .
   a. 取代 define
     #define D_INT 100
     #define D_LONG 100.29
     ………
     const int D_INT = 100;
     const D_INT = 100;     // 如果定义的 int 类型 , 可省略 int.
     const long D_LONG = 100.29;
     ………
     const int& a = 100; 
     const 替代 define 虽然增加分配空间 , 可它却保证了类型安全 .
     在 C 标准中 ,const 定义的数据相当于全局的 , 而 C++ 中视声明的位置而定 .
   b. 修饰指针相关的变量 
     以三组简单的定义示意: 
     Group1:   
     int a = 0;    
     const int* b = &a;------------  [1]                
     int const *b = &a;------------  [2]                     
     const int* const b = &a;---- [4]   
          
     Group2:  
     const char *p = "const";--------------[1] 
     char const *p = "const";--------------[2]   
     char* const p = "const";--------------[3]   
     const char * const p = "const";----[4]      
     
     Group3:
      int a=0;
        const int &b = a;---------------[1]
     int const &b = a;---------------[2]  
     int & const b = a;--------------[3]  //---> 修饰引用时 ,const 被忽略 
     const int & const b = a;-----[4]
     总结: 
     1. 如果 const 位于星号左侧 , 则 const 用来修饰指针所指向的变量 ,
       即指针指向的为不可变的 .
     2. 如果 const 位于星号右侧 ,const 就是修饰指针本身 , 即指针本身是 
       不可变的 .
       因此 ,[1] 和 [2] 的情况相同 , 指针所指向内容不可变 (const 放在变量 
       声明符的位置无关 ),
       这种情况下不允许对内容进行更改 , 如不能 *a = 3 ;
     3.[3] 中指针本身是不可变的,而指针所指向的内容是可变的 , 这种情况 
       下不能对指针本身 
       进行更改操作 , 如 a++ 是错误的 
     4.[4] 中指针本身和指向的内容均为常量 .( 引用特殊:引用在使用增加 
       遇义时 , 增加它代表的变量 . 所以 qualifiers on reference are ignoredv.
       延伸点 : 
       注意示例 :
       1.const int& reference = 1000; 
       2.char* p = "const"
         char*& q ;
   
2.const 在函数环境下的各种应用 
   常用法示例如下: 
   const A&  _Fun(const  A& _in);  // 修饰引用型传入参数 
   // A  _Fun(const A& _in);
   //A& _Fun(const A& _in);
   // 上面的两种 , 在函数内部有特殊的步骤 , 这里不详提了… ..
  
   const  A*  _Fun( const  A* _in);   // 修饰指针型传入参数 
   void _Fun( ) const;   // 修饰 class 成员函数 
   const  A&  _Fun(A& _in );  // 修饰返回值 
   const A & operator(const A& _in);  // 同时修饰传入参数和返回值

   a. 修饰参数 
     如 void _Fun(const A* _in) 或 void _Fun(const A& _in);
     它们被修饰后 , 在函数执行期间行为特性同于上面的讲解 ,
     注意:这不会改变原来数据的是否是 const 的属性 .

   b. 修饰函数返回值 
    const A&  _Fun( )
    const A*   _Fun( );
    注意:由于生命期不同步的问题 , 不可将局部的变量的指针或引用返回 (static 除外 ).
    另外 , 传出来的视情况 , 代表不同的意思… 
    对于 A& 返回类型 , 你若将之赋与其它变量 , 那么它实际执行的是将返回的变量 
    ( 或引用 ) 代表的数据赋出 .. 而你若将其它值赋予之 , 那么被赋予的是变量或引 
    用代表的数据 . 而 const A& 一般是防止之做为左值被赋值 .

    这个地方还有很多的细节问题 ( 譬如在连续赋值、返回的临时对象的处理、 
    重载的 const 和非 cosnt 运算符等等 ), 读者自己在实践中需要多多总结 .

二、难点 
3. 修饰类成员函数的 const.
   形如 :void _Fun() const { };
   你需要知道的几点规则:

   a.const 对象只能访问 const 成员函数 , 而非 const 对象可以访问任意 
     的成员函数 , 包括 const 成员函数 .
   b.const 对象的成员是不可修改的 , 然而 const 对象通过指针维护的对象却 
     是可以修改的 .
   c.const 成员函数不可以修改对象的数据 , 不管对象是否具有 const 性质 . 它在 
     编译时 , 以是否修改成员数据为依据 , 进行检查 .
   e. 然而加上 mutable 修饰符的数据成员 , 对于任何情况下通过任何手段 
     都可修改 , 自然此时的 const 成员函数是可以修改它的…

4. 谈谈 volatile 和”完全 const 对象” 
  一个有 volatile 修饰的类只允许访问其接口的一个子集,这个子集由类的 
  实现者来控制 . 用户只有用 const_cast 才可以访问这个类型的全部接口 . 而且 ,
  象 const 一样,类的 volatile 属性会传递给它的成员 . 想象 const 修饰的对 
  象 , 它的成员变量是不可修改的 , 而它通过指针维护的对象或原生变量是可 
  修改 . 那么我们想 : 如果对象维护一个 char* , 则它相当于 char* 
  const chrptr ; 而不是 const char* cosnt chrptr; 对于类中的指针你需要 
  这样修饰以防止它或它维护的资源: cosnt x* xptr; 而不是 x*const xptr; 
  因为 cosnt 修饰的对象它默认 的行为是延续变量: x* cosnt xptr;

  更重要的 ,volatile 修饰的数据 , 编译器不可对其进行执行期寄存于寄存器的优化 .
  这种特性 , 是为了多线程同步的需要 . 有兴趣者看参看 Andrei 的 GP 系列文章 .

5. 谈谈 const_cast 转换运算符 
  这个关键字最基础的用法是:去掉数据的 const 性质 .
  值得注意的是:它只对指针、引用和其它的具有指向性质的类型 .

时间: 2024-11-10 10:05:00

C++基本功:全面掌握const、volatile和mutable关键字的相关文章

C语言中const,volatile,restrict的用法总结_C 语言

1. const 变量声明中带有关键词const,意味着不能通过赋值,增量或减量来修改该变量的值,这是显而易见的一点.指针使用const则要稍微复杂点,因为不得不把让指针本身成为const和指针指向的值成为const区别开来.下面的声明表示pf指向的值必须是不变的 constfloat *pf:而pf则是可变的,它可以指向另外一个const或非const值:相反,下面的声明说明pf是不能改变的,而pf所指向的值则是可以改变的: float* const pf: 最后,当然可以有既不能改变指针的值

C++高级进阶 第二季:mutable 关键字

零.文章来由 打算将基础知识在看书的同时系统的整理一下,方便大家也方便自己.整理的知识尽量参照书本知识,比网上获取的资料有更高的可信度. 一.作用 mutable 用来解决常函数中不能修改对象的数据成员的问题. 如果在一些情况下,希望在常函数中仍然可以修改某个成员变量的值,就在该变量前加上mutable.能在保证常量对象大部分数据成员仍然"只读"情况下,实现对个别成员的修改. #include <iostream> #include <string> using

C语言中auto,register,static,const,volatile的区别详细解析_C 语言

1)auto这个关键字用于声明变量的生存期为自动,即将不在任何类.结构.枚举.联合和函数中定义的变量视为全局变量,而在函数中定义的变量视为局部变量.这个关键字不怎么多写,因为所有的变量默认就是auto的. (2)register这个关键字命令编译器尽可能的将变量存在CPU内部寄存器中而不是通过内存寻址访问以提高效率. (3)static常见的两种用途:1>统计函数被调用的次数; 2>减少局部数组建立和赋值的开销.变量的建立和赋值是需要一定的处理器开销的,特别是数组等含有较多元素的存储类型.在一

区分const,static,readonly,volatile四个关键字

const:表示常量,变量的值是绝不会被改变的,常量的值是在编译时就已经确定了.编译器会把常量的值保存在程序集的元素据里面,在C#里面,下面列举的简单类型才能被定义为 常量:Boolean,  Char,  Byte,  SByte,  Int16,  UInt16 ,  Int32,  UInt32 ,  Int64, UInt64 ,  Single ,  Double ,  Decimal, String.如果定一个引用类型为常量,则必须把该变量的值设为null.因为常量的值是不会改变的,

C++关键字static,const,volatile详解

static static修饰局部变量           static修饰局部变量用于修改变量的存储位置,从自动变量修改为静态变量(在静态区开辟空间,不在栈上开辟),但变量的链接属性和作用域不受影响.static修饰局部变量时该变量在程序执行之前创建,并在程序的整个执行空间一直存在,即使出了作用域也只是被隐藏并不销毁该变量.请看下面的两段代码             代码一:没有static修饰的局部变量           int main() {  int i=0;  for(i=0;i<

深入理解C++中的mutable关键字

mutalbe的中文意思是"可变的,易变的",跟constant(既C++中的const)是反义词. 在C++中,mutable也是为了突破const的限制而设置的.被mutable修饰的变量,将永远处于可变的状态,即使在一个const函数中. 我们知道,如果类的成员函数不会改变对象的状态,那么这个成员函数一般会声明成const的.但是,有些时候,我们需要在const的函数里面修改一些跟类状态无关的数据成员,那么这个数据成员就应该被mutalbe来修饰. 下面是一个小例子: class

深入解析C++中的mutable关键字_C 语言

mutalbe的中文意思是"可变的,易变的",跟constant(既C++中的const)是反义词. 在C++中,mutable也是为了突破const的限制而设置的.被mutable修饰的变量,将永远处于可变的状态,即使在一个const函数中. 我们知道,如果类的成员函数不会改变对象的状态,那么这个成员函数一般会声明成const的.但是,有些时候,我们需要在const的函数里面修改一些跟类状态无关的数据成员,那么这个数据成员就应该被mutalbe来修饰. 下面是一个小例子: 复制代码

C/C++中static,const,inline三种关键字详细总结_C 语言

一.关于staticstatic 是C++中很常用的修饰符,它被用来控制变量的存储方式和可见性,下面我将从 static 修饰符的产生原因.作用谈起,全面分析static 修饰符的实质. static 的两大作用: 一.控制存储方式 static被引入以告知编译器,将变量存储在程序的静态存储区而非栈上空间. 引出原因:函数内部定义的变量,在程序执行到它的定义处时,编译器为它在栈上分配空间,大家知道,函数在栈上分配的空间在此函数执行结束时会释放掉,这样就产生了一个问题: 如果想将函数中此变量的值保

浅谈C++中的mutable和volatile关键字_C 语言

1.mutable 在C++中,mutable是为了突破const的限制而设置的.被mutable修饰的变量,将永远处于可变的状态,即使在一个const函数中,甚至结构体变量或者类对象为const,其mutable成员也可以被修改.mutable在类中只能够修饰非静态数据成员. #include <iostream> using namespace std; class test { mutable int a; int b; public: test(int _a,int _b) :a(_a