大家好,我是网域小星球。
本篇是 C++ 面试补充的最后一篇,聚焦 3 个面试高频进阶考点------ 运算符重载、异常处理、动态内存进阶,都是基础面试中 "拉开差距" 的知识点,也是笔试常考的手撕题。学完这两篇补充,你的 C++ 面试基础会更扎实,轻松应对面试官的延伸提问,代码全部 VS2022 可运行。
目录
[1. 核心概念](#1. 核心概念)
[2. 核心规则(面试必背)](#2. 核心规则(面试必背))
[3. 常用运算符重载(笔试手撕示例)](#3. 常用运算符重载(笔试手撕示例))
[示例 1:重载 + 运算符(成员函数)](#示例 1:重载 + 运算符(成员函数))
[示例 2:重载 << 运算符(友元函数,高频)](#示例 2:重载 << 运算符(友元函数,高频))
[1. 核心作用](#1. 核心作用)
[2. 核心语法(面试必背)](#2. 核心语法(面试必背))
四、动态内存进阶(new/delete、智能指针,面试高频)
[1. C++ 动态内存管理(new/delete,替代 C 语言 malloc/free)](#1. C++ 动态内存管理(new/delete,替代 C 语言 malloc/free))
[2. 智能指针入门(面试高频,了解即可)](#2. 智能指针入门(面试高频,了解即可))
一、核心学习目标(面试导向)
- 掌握 运算符重载(语法 + 常用重载,笔试手撕题)
- 理解 异常处理(try-catch-throw)(面试必问用法)
- 吃透 动态内存进阶(new/delete、智能指针入门,避免内存泄漏)
- 掌握三大知识点的面试标准答案和代码写法
二、运算符重载(笔试手撕高频,面试必问)
1. 核心概念
C++ 允许重载运算符(如 +、-、*、==、<< 等),让自定义类的对象,能像内置类型(int、double)一样使用运算符,提高代码简洁性。
2. 核心规则(面试必背)
- 不能重载的运算符(牢记):
.、.*、::、? :、sizeof; - 重载运算符的优先级、结合性,与原运算符一致;
- 运算符重载本质是函数,分为 成员函数重载 和 友元函数重载。
3. 常用运算符重载(笔试手撕示例)
示例 1:重载 + 运算符(成员函数)
实现两个 Person 对象的年龄相加:
cpp
#include <iostream>
#include <string>
using namespace std;
class Person
{
public:
int age;
Person(int a) { age = a; }
// 重载 + 运算符(成员函数)
Person operator+(const Person& p)
{
Person temp(0);
temp.age = this->age + p.age; // this指向当前对象
return temp;
}
};
int main()
{
Person p1(20), p2(18);
Person p3 = p1 + p2; // 等价于 p1.operator+(p2)
cout << "年龄和:" << p3.age << endl; // 输出38
return 0;
}
示例 2:重载 << 运算符(友元函数,高频)
实现 cout 直接输出自定义对象(笔试常考):
cpp
class Person
{
private:
string name;
int age;
// 友元函数重载 <<
friend ostream& operator<<(ostream& cout, const Person& p);
public:
Person(string n, int a) : name(n), age(a) {}
};
// 友元函数重载 <<(类外定义)
ostream& operator<<(ostream& cout, const Person& p)
{
cout << "姓名:" << p.name << ",年龄:" << p.age;
return cout; // 返回cout,支持链式输出(如cout << p1 << p2)
}
int main()
{
Person p("张三", 20);
cout << p << endl; // 直接输出对象,等价于 operator<<(cout, p)
return 0;
}
面试常问
- 为什么 << 运算符重载要用友元函数?答:因为 cout 是 ostream 类的对象,若用成员函数重载,左操作数必须是当前类对象(如 p << cout),不符合使用习惯;友元函数可让左操作数是 cout,右操作数是自定义对象,符合常规用法。
三、异常处理(try-catch-throw,面试必问)
1. 核心作用
捕获程序运行时的异常(如除 0、数组越界、动态内存申请失败),避免程序直接崩溃,提高程序健壮性。
2. 核心语法(面试必背)
cpp
try
{
// 可能出现异常的代码
throw 异常值; // 抛出异常
}
catch (异常类型1)
{
// 捕获并处理异常类型1
}
catch (异常类型2)
{
// 捕获并处理异常类型2
}
catch (...)
{
// 捕获所有类型异常(兜底)
}
- 代码示例(面试常考场景)
cpp
#include <iostream>
using namespace std;
// 除法函数,抛出除0异常
int divide(int a, int b)
{
if (b == 0)
{
// 抛出异常(可抛出任意类型:int、string等)
throw "除0错误!";
}
return a / b;
}
int main()
{
int x = 10, y = 0;
try
{
int res = divide(x, y); // 可能出现异常
cout << "结果:" << res << endl;
}
catch (const char* err) // 捕获char*类型异常
{
cout << "异常捕获:" << err << endl; // 输出异常信息
}
catch (...) // 兜底,捕获所有未匹配的异常
{
cout << "未知异常!" << endl;
}
// 异常处理后,程序继续执行(不会崩溃)
cout << "程序正常执行完毕" << endl;
return 0;
}
面试常问
- C++ 异常处理的优点?答:分离异常检测和异常处理代码,提高代码可读性、可维护性;避免程序直接崩溃,增强程序健壮性。
- throw 抛出的异常,必须被 catch 捕获吗?答:不一定;若未被 catch 捕获,会调用系统默认异常处理函数,程序依旧会崩溃。
四、动态内存进阶(new/delete、智能指针,面试高频)
1. C++ 动态内存管理(new/delete,替代 C 语言 malloc/free)
核心区别(面试必问)
| 对比维度 | new/delete(C++) | malloc/free(C) |
|---|---|---|
| 本质 | 运算符(不是函数) | 库函数 |
| 类型检查 | 有严格类型检查 | 无类型检查(返回 void*) |
| 构造 / 析构 | 自动调用构造 / 析构 | 不调用,需手动初始化 / 释放 |
| 内存分配 | 直接分配对应类型内存 | 需手动计算内存大小 |
代码示例
cpp
#include <iostream>
using namespace std;
class Person
{
public:
Person() { cout << "构造调用" << endl; }
~Person() { cout << "析构调用" << endl; }
};
int main()
{
// 1. 动态分配单个对象
Person* p1 = new Person; // 自动调用构造
delete p1; // 自动调用析构,释放内存
p1 = nullptr; // 置空,避免野指针
// 2. 动态分配数组
Person* p2 = new Person[3]; // 调用3次构造
delete[] p2; // 必须加[],否则只调用1次析构,内存泄漏
p2 = nullptr;
return 0;
}
面试坑点
- 动态分配数组时,
delete必须加[],否则会导致内存泄漏; - new 申请内存失败时,会抛出
bad_alloc异常(C++11 后); - 避免内存泄漏:new 和 delete 必须成对出现,最好用智能指针管理。
2. 智能指针入门(面试高频,了解即可)
核心作用
自动管理动态内存,无需手动 delete,彻底避免内存泄漏(面试常问 "如何避免内存泄漏",智能指针是核心答案)。
常用智能指针(面试必记)
unique_ptr:独占所有权,一个智能指针只能指向一个对象,不能拷贝;shared_ptr:共享所有权,多个智能指针可指向同一个对象,自动计数,计数为 0 时释放内存;weak_ptr:辅助 shared_ptr,解决循环引用问题。
代码示例(unique_ptr,最基础)
cpp
#include <iostream>
#include <memory> // 智能指针头文件
using namespace std;
class Person
{
public:
~Person() { cout << "析构调用,内存释放" << endl; }
};
int main()
{
// 智能指针自动管理内存,无需手动delete
unique_ptr<Person> p(new Person);
// 自动释放,无需写delete
return 0;
}
面试常问
- 如何避免 C++ 内存泄漏?答:1. new 和 delete 成对出现;2. 使用智能指针(unique_ptr/shared_ptr);3. 避免野指针,及时置空;4. 析构函数中释放动态内存。
五、本章核心总结(面试速记)
- 运算符重载:让自定义对象可使用运算符,<< 重载常用友元,不能重载 5 个特殊运算符;
- 异常处理:try 捕获、throw 抛出、catch 处理,避免程序崩溃,提高健壮性;
- 动态内存:new/delete 自动调用构造 / 析构,智能指针可自动管理内存,避免泄漏;