C++ 关键字的使用(const static explict reinterpret_cast)

来源:互联网 发布:js制作简易购物车页面 编辑:程序博客网 时间:2024/06/16 13:00

1  volatile
有些变量是用volatile关键字声明的。当两个线程都要用到某一个变量且该变量的值会被改变时,应该用volatile声明,该关键字的作用是防止优化编译器把变量从内存装入CPU寄存器中。如果变量被装入寄存器,那么两个线程有可能一个使用内存中的变量,一个使用寄存器中的变量,这会造成程序的错误执行。 volatile的意思是让编译器每次操作该变量时一定要从内存中真正取出,而不是使用已经存在寄存器中的值,如下:   
  volatile   BOOL   bStop   =   FALSE;   
    
  
在一个线程中:   
  while(   !bStop   )   
  {   
    ...   
  }   
  bStop   =   FALSE;   
  return;     
    
  
在另外一个线程中,要终止上面的线程循环:   
  bStop   =   TRUE;   
  while(   bStop   );   //
等待上面的线程终止,如果bStop不使用volatile申明,那么这个循环将是一个死循环,因为bStop已经读取到了寄存器中,寄存器中bStop的值永远不会变成FALSE,加上volatile,程序在执行时,每次均从内存中读出bStop的值,就不会死循环了。 
这个关键字是用来设定某个对象的存储位置在内存中,而不是寄存器中。因为一般的对象编译器可能会将其的拷贝放在寄存器中用以加快指令的执行速度,例如下段代码中:   
  ...   
  int   nMyCounter   =   0;   
  for(;   nMyCounter<100;nMyCounter++)   
  {   
  ...   
  }   
  ...   
  
在此段代码中,nMyCounter的拷贝可能存放到某个寄存器中(循环中,对nMyCounter的测试及操作总是对此寄存器中的值进行),但是另外有又段代码执行了这样的操作:nMyCounter   -=   1;这个操作中,对nMyCounter的改变是对内存中的nMyCounter进行操作,于是出现了这样一个现象:nMyCounter的改变不是同步的 

                                                                                            
2  extern
2A 
c++中,还可用来指定使用另一语言进行链接,这时需要与特定的转换符一起使用。目前microsoft c/c++仅支持”c”转换标记,来支持c编译器链接。使用这种情况有两种形式:
u       extern “c” 声明语句
u       extern “c” { 声明语句块 }

2B  extern   LPDIRECTDRAW4       lpdd;  声明lpdd,但是不分配内存,只说明他是你可以用的变量,在此程序之外其他的程序中已经声名了他。 其实他就是防止名字冲突~  被其修饰的变量(外部变量)是静态分配空间的,即程序开始时分配,结束时释放
如果一个头文件被   #include   到一个以上的源文件   里,这个头文件中所有的定义就会出现在每一个有关的源码文件里。这会使它们里的符号被定义一次以上,从而出现连接错误。   
        
解决办法就是不要在头文件里定义变量。你只需要在头文件里声明它们然后在适当的源码文件(应该   #include   那个头文件的那个)里定义它们一次。extern告诉编译器其所声明的符号的存在,并不会使编译器分配贮存空间。当做一个声明而不是做定义的时候,在声明前放一个关键字“extern” 
extern
关键字的作用是声明变量和函数为外部链接,即该变量或函数名在其它文件中可见。用其声明的变量或函数应该在别的文件或同一文件的其它地方定义。 
例如语句:extern int a;
    
仅仅是一个变量的声明,其并不是在定义变量a,并未为a分配内存空间。变量a在所有模块中作为一种全局变量只能被定义一次,否则会出现连接错误。
    通常,在模块的头文件中对本模块提供给其它模块引用的函数和全局变量以关键字extern声明。例如,如果模块B欲引用该模块A中定义的全局变量和函数时只需包含模块A的头文件即可。这样,模块B中调用模块A中的函数时,在编译阶段,模块B虽然找不到该函数,但是并不会报错;它会在连接阶段中从模块A编译生成的目标代码中找到此函数

3  static
静态变量作用范围在一个文件内,程序开始时分配空间,结束时释放空间,默认初始化为0,使用时可改变其值。
静态变量或静态函数,即只有本文件内的代码才可访问它,它的名字(变量名或函数名)在其它文件中不可见。
在函数体内生成的静态变量它的值也只能维持
int max_so_far( int curr )//求至今(本次调用)为止最大值
{
   static int biggest; //
该变量保持着每次调用时的最新值,它的有效期等于整个程序的有效期
   if( curr > biggest )
   biggest = curr;
   return biggest;
}
c++类的成员变量被声明为static(称为静态成员变量),意味着它为该类的所有实例所共享,也就是说当某个类的实例修改了该静态成员变量,其修改值为该类的其它所有实例所见;而类的静态成员函数也只能访问静态成员(变量或函数)。
类的静态成员变量必须在声明它的文件范围内进行初始化才能使用,private类型的也不例外。如,               
float savingsaccount::currentrate = 0.00154;   
(注:currentrate是类savingsaccount的静态成员变量)

4  register
  
register声明的变量称着寄存器变量,在可能的情况下会直接存放在机器的寄存器中;但对32位编译器不起作用,当global optimizations(全局优化)开的时候,它会做出选择是否放在自己的寄存器中;不过其它与register关键字有关的其它符号都对32位编译器有效。

5  auto
  
它是存储类型标识符,表明变量(自动)具有本地范围,块范围的变量声明(如for循环体内的变量声明)默认为auto存储类型。

6  const
 const
所修饰的对象或变量不能被改变,修饰函数时,该函数不能改变在该函数外面声明的变量也不能调用任何非const函数。在函数的声明与定义时都要加上const,放在函数参数列表的最后一个括号后。
 c++中,用const声明一个变量,意味着该变量就是一个带类型的常量,可以代替#define,且比#define多一个类型信息,且它执行内链接,可放在头文件中声明;但在c中,其声明则必须放在源文件(即.c文件)中,在cconst声明一个变量,除了不能改变其值外,它仍是一具变量,如
const int maxarray = 255;
char store_char[maxarray];  //c++
中合法,c中不合法

1.如果const位于星号左侧,const用来修饰指针所指向的变量,
       
即指针指向的为不可变的.
2.
如果const位于星号右侧,const就是修饰指针本身,即指针本身是
不可变的.


7 mutable关键字的用法 
关键字mutableC++中一个不常用的关键字,他只能用于类的非静态和非常量数据成员
我们知道一个对象的状态由该对象的非静态数据成员决定,所以随着数据成员的改变,
对像的状态也会随之发生变化
如果一个类的成员函数被声明为const类型,表示该函数不会改变对象的状态,也就是
该函数不会修改类的非静态数据成员.但是有些时候需要在该类函数中对类的数据成员
进行赋值.这个时候就需要用到mutable关键字了

mutable关键字提示编译器该变量可以被类的const函数修改

8 explicit
explicit
关键字用于取消构造函数的隐式转换,对有多个参数的构造函数使用explicit是个语法错误。


9 C++ 同时提供了四种新的强制转型形式(通常称为新风格的或 C++ 风格的强制转型):
const_cast<T>(expression)
dynamic_cast<T>(expression)
reinterpret_cast<T>(expression)
static_cast<T>(expression)
每一种适用于特定的目的:

  ·const_cast 一般用于强制消除对象的常量性。它是唯一能做到这一点的 C++ 风格的强制转型。

  ·dynamic_cast 主要用于执行安全的向下转型(safe downcasting,也就是说,要确定一个对象是否是一个继承体系中的一个特定类型。它是唯一不能用旧风格语法执行的强制转型。也是唯一可能有重大运行时代价的强制转型。(过一会儿我再提供细节。)

  ·reinterpret_cast 是特意用于底层的强制转型,导致实现依赖(implementation-dependent)(就是说,不可移植)的结果,例如,将一个指针转型为一个整数。这样的强制转型在底层代码以外应该极为罕见。在本书中我只用了一次,而且还仅仅是在讨论你应该如何为裸内存(raw memory)写一个调谐分配者(debugging allocator)的时候。

  ·static_cast 可以被用于强制隐型转换(例如,non-const 对象转型为 const 对象(就像 Item 3 中的),int 转型为 double,等等)。它还可以用于很多这样的转换的反向转换(例如,void* 指针转型为有类型指针,基类指针转型为派生类指针),但是它不能将一个 const 对象转型为 non-const 对象。(只有 const_cast 能做到。)

10. C++ 是没finally关键字的,通过析构函数将资源释放掉,在C++中通常使用RAII,即Resource Aquisition Is Initialization.
就是将资源封装成一个类,将资源的初始化封装在构造函数里,释放封装在析构函数里。要在局部使用资源的时候,就实例化一个local object。
在抛出异常的时候,由于local object脱离了作用域,自动调用析构函数,会保证资源被释放

throw

例如:explicit

      auto_ptr(element_type* __p = 0) throw() : _M_ptr(__p) { }

这是异常规范,只会出现在声明函数中,表示这个函数可能抛出任何类型的异常

void GetTag() throw(int);表示只抛出int类型异常
void GetTag() throw(int,char);表示抛出in,char类型异常
void GetTag() throw();表示不会抛出任何类型异常
void GetTag() throw(...);表示抛出任何类型异常

void GetTag() throw(int);表示只抛出int类型异常
并不表示一定会抛出异常,但是一旦抛出异常只会抛出int类型,如果抛出非
int类型异常,调用unexsetpion()函数,退出程序。

假如你加一个throw()属性到你的永远不会抛出异常的函数中,编译器会非常聪明的知道代码的意图和决定优化方式

转自:http://www.cnblogs.com/zpsy/articles/1810402.html