C/C++关键字
volatile
volatile的原意指不稳定的、易变的,volatile关键字提示编译器它修饰的变量随时可能改变,存储和读取变量,应该在内存中操作,而不是使用寄存器中的值。
C代码:
int yes = 1; while(yes) { func(); }
编译器生成的伪代码:
mov ax, yes label: if yes goto label
C代码:
volatile int yes = 1; while(yes) { func(); }
编译器生成的伪代码:
label: mov ax, yes if yes goto label
通常而言,volatile用在以下场合:
- 中断服务中修改的变量。
- 多任务/多线程共享的数据。
- 存储器映射的硬件寄存器。
注意volatile并不能保证内存操作的原子性。
mutable
mutable表示可变的,与const是反义词。const表示对象不可变,或一个const函数表示函数内部不会修改对象状态,但mutable声明的变量不受const的限制:
class C { public: C() { _cprint = 0; } const void print() { printf("C::print()\n"); ++_cprint; } const int print_count() { return _cprint; } private: mutable int _cprint; };
原本const C::print()
不会修改对象内部状态,但为了计数打印次数,我们修改了C::_cprint
,这里C::_print用mutable修饰,因此不受const限制。
用const修饰对象:
struct person { int _age; int _level; }; const person p = { 27, 2 }; p._level = 3; // assignment of data-member ‘person::_level’ in read-only structure
用mutable修饰person::_level:
struct person { int _age; mutable int _level; };
使用mutable需要慎重,mutable出现的场合通常意味着这不是一个好的设计方案。
explicit
C++中有一个关键字explicit来规避类构造函数引起的隐式转换:
class Int { public: Int(int i) {} }; class Vector { public: explicit Vector(int i) {} }; int main() { Int i = 10; Vector v(10); return 0; }
throw
C++中的throw关键字与异常相关,常见两种用法:抛出异常;函数后追加throw,表示对函数抛出异常的限制。
函数后跟throw关键字的形式:
- void foo() throw() - foo()不允许抛出异常。
- void foo() throw(exception_type) - foo()允许抛出exception_type异常。
- void foo() throw(...) - foo()允许抛出任何异常。
例如C++标准库中异常类(std::exception)的定义,每个成员函数后都带throw(),即std::exception不允许抛出异常。
extern
extern关键字通常表明其声明的函数或变量在其他模块中定义。例如:
// bar.cpp int version = 1; // foo.cpp extern int version; int main() { printf("%d\n", version); return 0; }
编译运行:
$ g++ -c bar.cpp $ g++ foo.cpp bar.o $ ./a.out 1
extern "C"
extern "C"见于C++调用C库代码。C++支持重载,因此编译器会对函数名字做一些转换,例如加入返回/参数类型。例如这样一个函数foo:
int foo(int);
可能被编译器转换为_int_foo_int(或者其他形式),但C编译器不会这么干。C不支持函数重载,因此编译器生成的符号与C++符号不同。
在某些库的头文件中,我们常见如下的头文件结构:
#ifdef __cplusplus extern "C" { #endif /* code here */ #ifdef __cplusplus } #endif
C++编译器看到的代码是:
extern "C" { /* code here */ }
C编译器看到的代码是:
/* code here */