1.auto
用途:
用于编译器自动推断出变量类型,这里列举几种比较典型的情况:
(1)自动类型推导
auto x = 10; // x的类型是int
auto y = 3.14; // y的类型是double
auto z = 'c'; // z的类型是char
(2)与迭代器一起使用:
当处理STL容器时,auto
可以帮助我们自动推导迭代器的类型。
#include <vector>
#include <iostream>
using namespace std;
int main() {
vector<int> v = {1, 2, 3, 4, 5};
for (auto it = v.begin(); it != v.end(); ++it) {
cout << *it << ' ';
}
cout << '\n';
/*
当你有一个迭代器 it 时,*it 就是迭代器所指向的容器元素的值。在遍历容器时,你通常会使用 it++ 来将迭代器移动到容器的下一个元素,然后使用 *it 来访问该元素的值。
*/
// 使用C++11的基于范围的for循环(范围for循环)
for (auto elem : v) {
cout << elem << ' ';
}
cout << '\n';
return 0;
}
(3)与lambda表达式一起使用:
当在lambda表达式中捕获变量时,可以使用auto
来简化类型推导。
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
vector<int> v = {1, 2, 3, 4, 5};
// 使用auto推导lambda表达式中捕获的变量的类型
auto is_even = [&](auto x) { return x % 2 == 0; };
for (auto i : v) {
if (is_even(i)) {
cout << i << ' ';
}
}
cout << '\n';
return 0;
}
// 注意:上述lambda中的auto参数仅在C++14及更高版本中可用
2.nullptr
用途:
- 使用nullptr来初始化和比较指针。例如,
int* ptr = nullptr;
使用nullptr初始化了一个指向int类型的空指针。 - 当需要检查一个指针是否为空时,可以使用
if (ptr == nullptr) {...}
(1)类型安全:
- 在C++98/03中,空指针通常使用NULL宏来表示,这个宏通常被定义为0或((void*)0)。然而,这可能导致类型不明确的问题,因为NULL可以被隐式转换为任何指针类型。
- nullptr的引入解决了这个问题,它具有独立的类型std::nullptr_t,只能被赋值给指针类型或传递给需要空指针的函数,从而增加了类型安全性。
(2)区分空指针和零值:
- 在C++98/03中,NULL既可以表示空指针,也可以表示整数零,这可能会导致混淆。
- nullptr的引入使得空指针有了明确的表示,避免了这种混淆。
// C++11 之前
int* ptr1 = NULL;
int* ptr2 = 0;
// C++11 及以后
int* ptr3 = nullptr;
(3)与标准库的交互:
- C++标准库中的一些组件,如智能指针(unique_ptr和shared_ptr),需要一种明确的方式来表示空指针。使用nullptr可以确保这些组件正确地初始化和管理它们所拥有的资源。
(4)提高代码的可读性和可维护性:
- 使用nullptr可以使代码更加清晰,因为它明确表示了一个指针没有指向任何对象。这有助于减少由于空指针使用不当而导致的错误,并使代码更容易理解和维护。
(5)函数重载:
- 在函数重载中,nullptr的表现优于NULL或0。例如,如果有一个函数既接受整数参数又接受指针参数,并且你希望传递一个空指针参数,使用nullptr可以明确调用接受指针参数的函数版本,而使用0则会调用接受整数参数的版本。
#include <iostream>
using namespace std;
// 函数重载,接受 int* 参数
void foo(int* ptr) {
cout << "foo(int*): Received a pointer." << endl;
// 这里可以执行与 ptr 相关的操作
}
// 函数重载,接受 int 参数
void foo(int value) {
cout << "foo(int): Received an integer." << endl;
// 这里可以执行与 value 相关的操作
}
int main() {
// 使用 nullptr 明确调用接受 int* 参数的 foo 函数
foo(nullptr); // 输出: foo(int*): Received a pointer.
// 使用 0 会导致调用接受 int 参数的 foo 函数,因为 0 可以隐式转换为 int
foo(0); // 输出: foo(int): Received an integer.
// 正常使用 int* 类型的指针
int x = 42;
foo(&x); // 输出: foo(int*): Received a pointer.
return 0;
}
(6)RAII原则:
- RAII(Resource Acquisition Is Initialization)是C++中的一个重要概念,它强调资源的获取和释放应该与对象的生命周期绑定。nullptr的使用有助于实现这一原则,因为它提供了一种明确的方式来表示一个指针没有拥有任何资源。