修饰符
学习C++的时候,感觉各种各样花里胡哨的修饰符太多了,有必要做一个归纳。修饰符用来提供更丰富的语义,以便于编译器检查或优化。
函数修饰符
const
:用于成员函数,指明该函数不会修改类的任何非静态数据成员(除了被 mutable
修饰的成员)。const
修饰的成员函数可以被称为常量成员函数,它们可以在常量对象上被调用。类的getter是典型的例子。
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 阻止函数在更派生的类中被重写。作为类修饰符时,阻止类被继承。
static
:用于类的成员函数,表明该函数不依赖于类的实例。静态成员函数只能访问静态数据成员或调用其他的静态成员函数。
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
可以用于任何数据类型,包括基本类型、对象、指针和引用。
static
:用于声明变量的存储持续性为整个程序的运行期。在函数内部声明为 static
的变量在函数调用结束后不会被销毁,而会保持其值直到下次调用。
void function() {
static int counter = 0; // 每次调用函数时,counter 的值都被保留
counter++;
std::cout << counter << std::endl;
}
volatile
:用来告诉编译器,变量的值可能会在程序的控制之外被改变(例如,通过操作系统、硬件或并发线程)。这阻止编译器对涉及易变变量的代码进行某些类型的优化。
extern
:用于声明一个全局变量的引用,该变量在另一个文件中定义。extern
用来在多个文件之间共享变量。
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)。每个线程有其自己的变量实例。这用于并发编程,确保数据在多线程环境中的安全使用。
这些修饰符使得开发者可以更精确地控制程序的行为,从而优化性能,增强程序的健壮性和线程安全性。