跳转至

修饰符

学习C++的时候,感觉各种各样花里胡哨的修饰符太多了,有必要做一个归纳。修饰符用来提供更丰富的语义,以便于编译器检查或优化。

函数修饰符

const:用于成员函数,指明该函数不会修改类的任何非静态数据成员(除了被 mutable 修饰的成员)。const 修饰的成员函数可以被称为常量成员函数,它们可以在常量对象上被调用。类的getter是典型的例子。

class MyClass {
public:
    int value() const { return data_; } // 不会修改任何成员变量
private:
    int data_;
};

constexpr:用于指示函数或对象构造函数在编译时可被求值,使得函数或对象可以用在需要常量表达式的场景,如数组大小、整数模板参数等。

explicit:用于构造函数或转换函数,阻止编译器进行隐式类型转换,要求必须显式调用构造函数或转换函数。

class MyClass {
public:
    explicit MyClass(int x) : data_(x) {}
private:
    int data_;
};

MyClass obj = MyClass(10); // 正确
MyClass obj = 10; // 错误,因为禁止了隐式转换

virtual:用于成员函数,表明该函数是虚函数,允许在派生类中被重写。这是实现多态行为的基础。如果在函数后面有=0表示该函数是纯虚函数,必须在派生类中重写。 override:用于派生类的成员函数,明确指出该函数意在重写基类中的虚函数。这有助于编译器检查函数签名的匹配性。

class Base {
public:
    virtual void foo() { std::cout << "Base::foo()\n"; }
};

class Derived : public Base {
public:
    void foo() override { std::cout << "Derived::foo()\n"; }
};

final:可以用于成员函数或类。作为成员函数修饰符时,final 阻止函数在更派生的类中被重写。作为类修饰符时,阻止类被继承。

class Base {
public:
    virtual void foo() final; // 不能在派生类中被重写
};

class NoInherit final { // 不能被继承
};

static:用于类的成员函数,表明该函数不依赖于类的实例。静态成员函数只能访问静态数据成员或调用其他的静态成员函数。

class MyClass {
public:
    static void staticFunc() { std::cout << "Static function.\n"; }
};

noexcept:表明函数不会抛出异常。这有助于编译器优化性能,同时也是对调用者的一个重要提示。

void myFunction() noexcept {
    // 函数保证不抛出异常
}

=default是 C++11 引入的一个特性,告诉编译器使用默认的实现。当声明一个特殊成员函数(如构造函数、析构函数等)时,使用 =default 可以明确要求编译器生成默认版本。

class MyClass {
public:
    // 默认构造函数
    MyClass() = default;

    // 默认析构函数
    ~MyClass() = default;

    // 默认拷贝构造函数
    MyClass(const MyClass&) = default;

    // 默认拷贝赋值运算符
    MyClass& operator=(const MyClass&) = default;
};

变量修饰符

在 C++ 中,变量修饰符用以指定变量的存储类别、链接属性、生命周期和其他行为特性。这些修饰符对于编写高效和可靠的程序至关重要。以下是 C++ 中常用的一些变量修饰符:

const:指示变量的值不能被修改。const 可以用于任何数据类型,包括基本类型、对象、指针和引用。

const int MAX_SIZE = 100;
const std::string TITLE = "My Program";

static:用于声明变量的存储持续性为整个程序的运行期。在函数内部声明为 static 的变量在函数调用结束后不会被销毁,而会保持其值直到下次调用。

void function() {
    static int counter = 0;  // 每次调用函数时,counter 的值都被保留
    counter++;
    std::cout << counter << std::endl;
}

volatile:用来告诉编译器,变量的值可能会在程序的控制之外被改变(例如,通过操作系统、硬件或并发线程)。这阻止编译器对涉及易变变量的代码进行某些类型的优化。

volatile int ready = 0;

extern:用于声明一个全局变量的引用,该变量在另一个文件中定义。extern 用来在多个文件之间共享变量。

extern int globalValue;  // 在其他文件中定义的变量

mutable:允许在一个 const 成员函数中修改某些类成员变量。即使类的对象是常量,被 mutable 修饰的成员变量也可以被修改。

class MyClass {
public:
    void updateCache() const { cache = fetchData(); }  // const 函数中修改成员
    int fetchData() const { return 42; }

private:
    mutable int cache;  // 即使在 const 对象中也可以修改
};

register:(已在 C++17 中弃用)原意是建议编译器将变量存储在寄存器中,以便快速访问。现在这个关键字不再有任何实际效果,但仍可用于语法兼容性。

thread_local:指示变量具有线程局部存储(TLS)。每个线程有其自己的变量实例。这用于并发编程,确保数据在多线程环境中的安全使用。

thread_local int threadSpecificData = 0;

这些修饰符使得开发者可以更精确地控制程序的行为,从而优化性能,增强程序的健壮性和线程安全性。