1 nullptr
nullptr是C++11引入的关键字,用于表示空指针。
1.1 为什么要引入nullptr ?
在C++中,指针是一个特殊的数据类型,可以存储其它变量的地址。通常情况下,指针可以指向一个有效的地址,即指向有效的内存空间。然而,在某些情况下,我们希望将指针置为空,表示它不指向任何有效的地址。这在编程中是非常有用的,例如在函数中将指针初始化为空,然后在需要时再为其赋值。
在C++11之前,通常使用NULL来表示空指针。但是,NULL是一个宏定义,同时也是整数常量0的别名。这意味着NULL在某些情况下可能会引发一些意外的行为。
为了解决这个问题,C++11引入了nullptr关键字。nullptr的意思是“空指针”,它的类型是std::nullptr_t。nullptr可以用来初始化任何指针类型,且不会导致一些潜在的类型转换问题。同时,nullptr还支持与指针相关的比较操作。
1.2 nullptr的高级用法
- 函数重载和模板推断
nullptr可以帮助区分函数重载或模板推断的正确选择。在C++中,函数重载和模板推断时,往往需要根据参数类型来进行选择。如果我们使用NULL来表示空指针,编译器可能会将它解释成整数0,而不是指针类型。而使用nullptr作为参数则可以明确指示空指针。
void foo(int);
void foo(char*);
foo(nullptr); // 调用void foo(char*)
- 安全的类型转换
nullptr在类型转换中更安全。在C++中,指针类型可以隐式转换为bool类型。如果我们使用NULL进行隐式转换,可能会导致一些意外行为,因为NULL实际上是一个整数常量0的别名。使用nullptr作为nullptr_t类型,可以确保只有指针类型可以隐式转换为bool类型。这使得代码更容易阅读和理解。
void foo(int);
void foo(bool);
foo(nullptr); // 调用void foo(bool)
- 安全的成员访问
使用nullptr可以安全地进行成员访问操作。在C++中,我们可以使用指针访问成员变量或成员函数,但是如果指针为空,则会导致运行时错误。使用nullptr可以帮助我们在访问成员之前进行空指针检查,从而避免出现访问空指针的情况。
struct Foo {
void bar() { std::cout << "I am bar!" << std::endl; }
};
Foo* ptr = nullptr;
if (ptr != nullptr) {
ptr->bar(); // 进行空指针检查,避免访问空指针
}
2 强类型枚举(enum class)
强类型枚举(enum class)是C++11中引入的一种新的枚举类型。与传统的枚举类型相比,强类型枚举具有更强的类型安全性和作用域限制。
传统的枚举类型在C++中是一个整数类型,它的值可以隐式地转换为整型。这可能导致一些潜在的问题,如意外的类型转换和枚举值之间的命名冲突。为了解决这些问题,强类型枚举引入了新的语法和行为。
2.1 基本语法
强类型枚举使用enum class
关键字来定义,其基本语法如下:
enum class EnumName : underlying_type {
enumerator1,
enumerator2,
// ...
};
其中:
EnumName
是强类型枚举的名称,可以在命名空间内使用。underlying_type
是强类型枚举的潜在类型(underlying type),可以是int
、char
、enum
或其它整数类型。如果未指定潜在类型,则默认为int
类型。enumerator1
、enumerator2
等是枚举类型的枚举值,它们归属于EnumName
这个作用域。
下面是一个强类型枚举的示例:
enum class Color : int {
Red,
Green,
Blue
};
在强类型枚举中,枚举值的作用域被限制在枚举类型的作用域内。这意味着我们不能直接将枚举值与其它整型值混合使用,也不能直接将枚举值隐式地转换为整型。
Color color = Color::Red;
int value = static_cast<int>(color); // 需要显式的类型转换
if (color == Color::Green) {
// ...
}
这种强类型枚举的更严格的类型转换规则和作用域限制使得代码更加安全和可读,并且可以避免一些潜在的错误。当需要使用枚举类型时,推荐使用强类型枚举(enum class)来代替传统的枚举类型(enum)。
2.2 enum class常见用法
- 枚举值的位操作
强类型枚举的枚举值可以进行位操作,这在处理一组选项或标志时非常有用。可以使用位运算符(如|
、&
、~
)对具有位模式的枚举值进行操作。
enum class Permissions : unsigned int {
Read = (1 << 0),
Write = (1 << 1),
Delete = (1 << 2)
};
Permissions myPerm = Permissions::Read | Permissions::Write;
- 自定义枚举值的整数值
可以为强类型枚举的枚举值显式地设置整数值。这有助于与现有的枚举类型或其他库进行兼容。
enum class Result : int {
Success = 0,
Failure = -1
};
- 枚举值的迭代
可以通过static_cast
将枚举类型转换为其潜在类型,然后进行迭代。这对于遍历枚举值的所有可能选项很有帮助。
enum class Size : int {
Small = 1,
Medium,
Large
};
for (int i = static_cast<int>(Size::Small); i <= static_cast<int>(Size::Large); ++i) {
// 处理每个枚举值
}