C/C++常见关键字含义和用法说明

在C/C++的使用过程中,虽然关键字整体数量不多,但是要记住,并完美的使用也并非易事,本人根据各方面查到的资料,对一些常见关键字进行收集和总结,希望对平时的开发有所作用。以下内容并非本人独创,只是平时学习笔记而已。

volatile(易变的)
作用是:确保本条指令不会因编译器的优化而被省略,且确保每次的操作都是直接读值,而非通过读取寄存器备份数据等优化方式。
比较常见的应用场景是在多线程中访问同一个共享变量时,需要使用volatile关键字来修饰这个共享变量,防止各线程间由于访问到不同的值而导致程序运行出现逻辑错误。

extern
作用是:标示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义。extern有两个作用:

  • 第一是当它与“C”一起使用时,例如 extern “C” void fun(int
    a),表示提示编译器在编译该fun函数时采用C的规则去翻译函数名。
  • 第二是直接修饰变量或函数时,则表示该变量或函数已在其他模块中被定义,此处只是用于声明。

static
在C++中分为了两种用法,一个是面向过程程序设计的(与C语言兼容),一个是面向对象程序设计的。
面向过程设计中的作用
用于定义静态全局变量,对于静态全局变量它具有如下特性:

  • 被定义的变量在全局数据区中进行分配内存;
  • 未经初始化的静态全局变量会被自动初始化为0(在实际编码中一定要记得显式初始化,防止出现不受控的结果);
  • 静态全局变量在声明它的文件内是都可见的,但在文件外是不可见的。

用于定义静态局部变量,对于静态局部变量有如下特性:

  • 该变量在全局数据区分配内存;
  • 静态局部变量在程序执行到该对象的声明处时被首次初始化,即以后的函数调用不再进行初始化;
  • 静态局部变量一般在声明处初始化,如果没有显式初始化,会被程序自动初始化为0;
  • 它始终驻留在全局数据区,直到程序运行结束。但其作用域为局部作用域,当定义它的函数或语句块结束时,其作用域随之结束。

静态函数
在函数返回类型前加上static关键字,则该函数被定义为静态函数。被定义为静态函数,则表明它只能在声明文件之中可见,不能被其它文件所使用,这样可以确保在其他文件中定义相同名字的函数时,不会发生定义冲突。

面向对象设计中的作用
静态数据成员
在类内数据成员的声明前加上关键字static,该数据成员就是类内的静态数据成员。静态数据成员有以下特点:

  • 对于非静态数据成员,每个类对象都有自己的拷贝。而静态数据成员被当作是类的成员。无论这个类的对象被定义了多少个,静态数据成员在程序中也只有一份拷贝,由该类型的所有对象共享访问。也就是说,静态数据成员是该类的所有对象所共有的。对该类的多个对象来说,静态数据成员只分配一次内存,供所有对象共用。所以,静态数据成员的值对每个对象都是一样的,它的值可以更新;
  • 静态数据成员存储在全局数据区。静态数据成员定义时要分配空间,所以不能在类声明中定义;
  • 静态数据成员和普通数据成员一样遵从public,protected,private访问规则;
  • 因为静态数据成员在全局数据区分配内存,属于本类的所有对象共享,所以,它不属于特定的类对象,在没有产生类对象时其作用域就可见,即在没有产生类的实例时,我们就可以操作它;
  • 静态数据成员初始化与一般数据成员初始化不同。静态数据成员初始化的格式为:

<数据类型><类名>::<静态数据成员名>=<值>;

  • 类的静态数据成员有两种访问形式:

<类对象名>.<静态数据成员名> 或 <类类型名>::<静态数据成员名>

  • 如果静态数据成员的访问权限允许的话(即public的成员),可在程序中,按上述格式来引用静态数据成员 ;

  • 静态数据成员主要用在各个对象都有相同的某项属性的时候。比如对于一个存款类,每个实例的利息都是相同的。所以,应该把利息设为存款类的静态数据成员。这有两个好处,第一,不管定义多少个存款类对象,利息数据成员都共享分配在全局数据区的内存,所以节省存储空间。第二,一旦利息需要改变时,只要改变一次,则所有存款类对象的利息全改变过来了;

  • 同全局变量相比,使用静态数据成员有两个优势:1、静态数据成员没有进入程序的全局名字空间,因此不存在与程序中其它全局名字冲突的可能性;2、可以实现信息隐藏。静态数据成员可以是private成员,而全局变量不能。

静态成员函数
与静态数据成员一样,我们也可以创建一个静态成员函数,它为类的全部服务而不是为某一个类的具体对象服务。静态成员函数与静态数据成员一样,都是类的内部实现,属于类定义的一部分。普通的成员函数一般都隐含了一个this指针,this指针指向类的对象本身,因为普通成员函数总是具体的属于某个类的具体对象的。通常情况下,this是缺省的。如函数fn()实际上是this->fn()。但是与普通函数相比,静态成员函数由于不是与任何的对象相联系,因此它不具有this指针。从这个意义上讲,它无法访问属于类对象的非静态数据成员,也无法访问非静态成员函数,它只能调用其余的静态成员函数。关于静态成员函数,具有以下几点特点:

  • 出现在类体外的函数定义不能指定关键字static;
  • 静态成员之间可以相互访问,包括静态成员函数访问静态数据成员和访问静态成员函数;
  • 非静态成员函数可以任意地访问静态成员函数和静态数据成员;
  • 静态成员函数不能访问非静态成员函数和非静态数据成员;
  • 由于没有this指针的额外开销,因此静态成员函数与类的全局函数相比速度上会有少许的增长;
  • 调用静态成员函数,可以用成员访问操作符(.)和(->)为一个类的对象或指向类对象的指针调用静态成员函数,也可以直接使用如下格式:<类名>::<静态成员函数名>(<参数表>),调用类的静态成员函数。

register
用register声明的变量称着寄存器变量,在可能的情况下会直接存放在机器的寄存器中。目前在新的C++11标准中,已没有任何明显作用,后续不排除被剔除。

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

const(常量)
修饰符const用于定义常类型,常类型的变量或对象的值是不能被更新的。对于const的主要作用有如下几点:

  • 用于定义const常量;
  • 使用const常量,方便进行类型检查。因为对于宏常量来讲是没有数据类型的,因此在进行字符替换时有可能会产生意料不到的错误;
  • 使用const修饰符可以保护被修饰的对象,防止被意外的修改,提高程序的健壮性;
  • 使用const常量可以节省内存空间,与#define宏定义不同,const定义的常量在程序运行过程中只有一份拷贝,而#define定义的常量在内存中有若干个拷贝。

主要使用点如下:
定义常量
const修饰变量,它的含义是:const修饰的类型对应的变量是不可变的。用const声明的变量虽然增加了分配空间,但是可以保证类型安全。C标准中,const定义的常量是全局的,C++中视声明位置而定。在使用过程中,“const” 与 “类型说明符”或“类名”的位置可以互换,如:

const int a=1; 与 int const a=1; 等同
类名 const 对象名 与 const 类名 对象名 等同

指针和常量
使用指针时涉及到两个对象:该指针本身和被它所指的对象。因此,在使用使用const修饰符时,就分为指向const对象的指针和指向对象的const指针。
区分这两者的方法是看const在定义中所处的位置,如果位于星号(*)左侧,表示指向一个const对象的指针,也就是所指向的内容为常量不可变,如果位于星号(*)右侧,则表示指针本身是一个常量不可变,例如:

char* const pValue; 得到char的const指针,故pValue不能指向别的字符串,但可以修改其指向的字符串的内容
const char* pValue; 得到const char的指针,故*pValue的内容不可以改变,但pValue可以指向别的字符串
const char* const pValue;得到const char的const指针,故*pValue的内容不可以改变,pValue也不可以指向别的字符串

修饰函数形参
将函数传入参数声明为const,以指明使用这种参数仅仅是为了效率的原因,而不是想让调用函数能够修改对象的值。通常修饰指针参数和引用参数居多:

void Fun(const ClassA *in); //修饰指针型传入参数
   void Fun(const ClassA &in); //修饰引用型传入参数

修饰函数返回值
可以阻止用户修改返回值。返回值也要相应的付给一个常量或常指针。一般多用于操作符的重载,其他情况很少使用。
修饰成员变量(c++特性)
const修饰类的成员函数,表示成员常量,不能被修改,同时被定义的成员常量只能在初始化列表中进行赋值:

 class A
   {const int nValue;         //成员常量不能被修改
        …
        A(int x): nValue(x) { } ; //只能在初始化列表中赋值
   } 

修饰成员函数(c++特性)
const修饰类的成员函数,则该成员函数不能修改类中任何非const成员函数:

class A
    {void function()const; //常成员函数, 它不改变对象的成员变量.                        
    }

const对象只能访问const成员函数,而非const对象可以访问任意的成员函数,包括const成员函数;
const对象的成员是不能修改的,而通过指针维护的对象却是可以修改的;
const成员函数不可以修改对象的数据,不管对象是否具有const性质,编译时以是否修改成员数据为依据进行检查。

mutable
在C++中,mutable是为了突破const的限制而设置的。被mutable修饰的变量,将永远处于可变的状态,即使在一个const函数中。
如果类的成员函数不会改变对象的状态,那么这个成员函数一般会声明成const的。但是,有些时候,我们需要在const的函数里面修改一些跟类状态无关的数据成员,那么这个数据成员就应该被mutalbe来修饰。

explicit
explicit关键字用来修饰类的构造函数,被修饰的构造函数的类,不能发生相应的隐式类型转换,只能以显示的方式进行类型转换。
explicit 关键字只能用于类内部的构造函数声明上。
explicit 关键字作用于单个参数的构造函数。

4种C++风格的强制转型
对应的语法:

    const_cast<new_type>(expression)
    static_cast<new_type>(expression)
    dynamic_cast<new_type>(expression)
    reinterpret_cast<new_type>(expression)

const_cast:允许添加或删除表达式类型的const或volatile关键字。它是唯一能做到这一点的 C++ 风格的强制转型。
static_cast:可以被用于强制隐型转换(例如,non-const 对象转型为 const 对象,int 转型为 double,等等),它还可以用于很多这样的转换的反向转换(例如,void* 指针转型为有类型指针,基类指针转型为派生类指针),但是它不能将一个 const 对象转型为 non-const 对象(只有 const_cast 能做到),它最接近于C-style的转换。
dynamic_cast:主要用于执行“安全的向下转型(safe downcasting)”,也就是说,要确定一个对象是否是一个继承体系中的一个特定类型。它是唯一不能用旧风格语法执行的强制转型,也是唯一可能有重大运行时代价的强制转型。
reinterpret_cast:是特意用于底层的强制转型,导致实现依赖(implementation-dependent)(不可移植)的结果,例如,将一个指针转型为一个整数。这样的强制转型在底层代码以外应该极为罕见。

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值