C++11新特性面试题
1. C++11引入了哪些重要特性?
答案:
- 语言核心特性auto类型推导decltype类型推导nullptr空指针范围for循环lambda表达式右值引用和移动语义变参模板constexpr常量表达式
- 标准库智能指针(shared_ptr、unique_ptr、weak_ptr)线程库(thread、mutex、condition_variable)正则表达式时间库(chrono)随机数库元组(tuple)
- 容器unordered_map、unordered_setarrayforward_list
2. auto关键字的作用和使用场景?
答案:
- 作用自动类型推导编译器根据初始化表达式推导类型必须初始化
- 使用场景
// 简化复杂类型
auto it = map.begin(); // 代替 map<int,string>::iterator
// 模板类型
template<typename T, typename U>
auto add(T t, U u) -> decltype(t + u) {
return t + u;
}
// 范围for循环
for (auto& elem : vec) {
// ...
}
// lambda表达式
auto lambda = [](int x) { return x * 2; };
- 注意事项auto会丢弃const和引用使用const auto&保留const和引用不能用于函数参数(C++14后可以)不能用于数组
3. lambda表达式的语法和使用?
答案:
- 基本语法
[捕获列表](参数列表) -> 返回类型 { 函数体 }
- 捕获方式[]:不捕获[=]:值捕获所有[&]:引用捕获所有[x]:值捕获x[&x]:引用捕获x[this]:捕获this指针[=, &x]:x引用捕获,其他值捕获
- 使用示例
// 简单lambda
auto add = [](int a, int b) { return a + b; };
// 捕获外部变量
int factor = 2;
auto multiply = [factor](int x) { return x * factor; };
// 用于STL算法
vector<int> v = {3, 1, 4, 1, 5};
sort(v.begin(), v.end(), [](int a, int b) { return a > b; });
// 可变lambda
int count = 0;
auto counter = [count]() mutable { return ++count; };
- 优势代码简洁就地定义可以捕获局部变量
4. 右值引用和移动语义是什么?
答案:
- 右值引用用&&声明:int&& rref = 10;绑定到临时对象延长临时对象生命周期
- 移动语义转移资源所有权,而非拷贝避免不必要的深拷贝提高性能
- 移动构造函数
class MyString {
char* data;
public:
// 移动构造
MyString(MyString&& other) noexcept
: data(other.data) {
other.data = nullptr;
}
// 移动赋值
MyString& operator=(MyString&& other) noexcept {
if (this != &other) {
delete[] data;
data = other.data;
other.data = nullptr;
}
return *this;
}
};
- std::move将左值转换为右值引用不移动任何东西,只是类型转换
string s1 = "hello"; string s2 = std::move(s1); // s1被移动,不再可用
5. nullptr和NULL的区别?
答案:
- NULL的问题NULL通常定义为0或(void*)0是整数类型,可能导致重载歧义
void func(int); void func(char*); func(NULL); // 可能调用func(int),不明确
- nullptrC++11引入的关键字类型是nullptr_t可以隐式转换为任何指针类型不能转换为整数
func(nullptr); // 明确调用func(char*)
- 使用建议C++11后统一使用nullptr类型安全避免歧义
6. 智能指针的使用场景?
答案:
- unique_ptr独占所有权不能拷贝,只能移动零开销
unique_ptr<int> p1(new int(10));
unique_ptr<int> p2 = std::move(p1); // 转移所有权
// 工厂函数
unique_ptr<Widget> createWidget() {
return make_unique<Widget>();
}
- shared_ptr共享所有权引用计数最后一个shared_ptr销毁时释放资源
shared_ptr<int> p1 = make_shared<int>(10); shared_ptr<int> p2 = p1; // 引用计数+1
- weak_ptr不控制生命周期打破循环引用需要lock()转换为shared_ptr使用
shared_ptr<int> sp = make_shared<int>(10);
weak_ptr<int> wp = sp;
if (auto sp2 = wp.lock()) {
// 使用sp2
}
7. 范围for循环的使用?
答案:
- 基本语法
for (元素类型 元素 : 容器) {
// 使用元素
}
- 使用示例
vector<int> vec = {1, 2, 3, 4, 5};
// 只读
for (int x : vec) {
cout << x;
}
// 修改(使用引用)
for (int& x : vec) {
x *= 2;
}
// 避免拷贝(const引用)
for (const auto& elem : vec) {
cout << elem;
}
- 原理编译器展开为迭代器循环要求容器有begin()和end()方法
- 注意事项不要在循环中修改容器大小使用引用避免拷贝可以用于数组、容器、初始化列表
8. constexpr的作用?
答案:
- 定义常量表达式编译期计算可用于常量上下文
- constexpr变量
constexpr int size = 10; int arr[size]; // 可以用作数组大小
- constexpr函数
constexpr int factorial(int n) {
return n <= 1 ? 1 : n * factorial(n - 1);
}
constexpr int result = factorial(5); // 编译期计算
- 与const的区别const:运行时或编译时常量constexpr:必须是编译时常量constexpr隐含const
- C++14扩展允许局部变量允许循环和条件语句
9. 变参模板的使用?
答案:
- 定义接受可变数量的模板参数使用...表示参数包
- 递归展开
// 基础情况
void print() {}
// 递归情况
template<typename T, typename... Args>
void print(T first, Args... args) {
cout << first << " ";
print(args...);
}
print(1, 2.5, "hello"); // 输出: 1 2.5 hello
- 折叠表达式(C++17)
template<typename... Args>
auto sum(Args... args) {
return (args + ...); // 一元右折叠
}
sum(1, 2, 3, 4); // 返回10
- 应用实现tuple完美转发可变参数函数
10. 线程库的基本使用?
答案:
- 创建线程
#include <thread>
void func(int x) {
cout << "Thread: " << x << endl;
}
thread t1(func, 10);
t1.join(); // 等待线程结束
- 互斥锁
#include <mutex>
mutex mtx;
int shared_data = 0;
void increment() {
lock_guard<mutex> lock(mtx); // RAII
shared_data++;
}
- 条件变量
#include <condition_variable>
mutex mtx;
condition_variable cv;
bool ready = false;
void wait_thread() {
unique_lock<mutex> lock(mtx);
cv.wait(lock, []{ return ready; });
// 继续执行
}
void signal_thread() {
{
lock_guard<mutex> lock(mtx);
ready = true;
}
cv.notify_one();
}
- 原子操作
#include <atomic> atomic<int> counter(0); counter++; // 原子操作
- 注意事项避免死锁使用RAII管理锁注意数据竞争优先使用高层抽象(如future、async)
C++面试总结 文章被收录于专栏
本专栏系统梳理C++面试高频考点,从基础语法、内存管理、STL与设计模式,到操作系统与项目实战,结合真实面试题深度解析,帮助开发者高效查漏补缺,提升技术理解与面试通过率,打造扎实的C++工程能力。
查看7道真题和解析
