首页 » C/C++ » C/C++关键字

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 */

分享

0