17.1 异常处理基础

#include <iostream>
#include <stdexcept>
using namespace std;

double divide(double a, double b) {
    if (b == 0) {
        throw runtime_error("除数不能为零");
    }
    return a / b;
}

int main() {
    try {
        cout << divide(10, 2) << endl;
        cout << divide(10, 0) << endl;
    } catch (const runtime_error& e) {
        cout << "捕获异常:" << e.what() << endl;
    }

    cout << "程序继续执行" << endl;
    return 0;
}

17.2 标准异常类

#include <iostream>
#include <exception>
#include <stdexcept>
#include <vector>
using namespace std;

int main() {
    try {
        // logic_error派生类
        throw invalid_argument("无效参数");

        // runtime_error派生类
        throw out_of_range("越界");

        // 数组越界
        vector<int> vec(5);
        vec.at(10) = 100;  // 抛出out_of_range

    } catch (const invalid_argument& e) {
        cout << "invalid_argument: " << e.what() << endl;
    } catch (const out_of_range& e) {
        cout << "out_of_range: " << e.what() << endl;
    } catch (const exception& e) {
        cout << "exception: " << e.what() << endl;
    }

    return 0;
}

17.3 自定义异常

#include <iostream>
#include <exception>
using namespace std;

class MyException : public exception {
private:
    string message;

public:
    MyException(const string& msg) : message(msg) {}

    const char* what() const noexcept override {
        return message.c_str();
    }
};

void process(int value) {
    if (value < 0) {
        throw MyException("值不能为负数");
    }
    cout << "处理值:" << value << endl;
}

int main() {
    try {
        process(10);
        process(-5);
    } catch (const MyException& e) {
        cout << "自定义异常:" << e.what() << endl;
    }

    return 0;
}

17.4 RAII与异常安全

#include <iostream>
#include <memory>
using namespace std;

class Resource {
public:
    Resource() { cout << "获取资源" << endl; }
    ~Resource() { cout << "释放资源" << endl; }
    void use() { cout << "使用资源" << endl; }
};

void riskyFunction() {
    // 使用智能指针保证异常安全
    unique_ptr<Resource> res(new Resource());
    res->use();

    // 即使抛出异常,析构函数也会被调用
    throw runtime_error("发生错误");
}

int main() {
    try {
        riskyFunction();
    } catch (const exception& e) {
        cout << "捕获:" << e.what() << endl;
    }

    return 0;
}

17.2 标准异常类层次结构

17.2.1 完整异常层次图

std::exception (基类)
├── logic_error (逻辑错误 - 程序逻辑问题)
│   ├── invalid_argument (无效参数)
│   ├── domain_error (数学域错误)
│   ├── length_error (长度错误)
│   ├── out_of_range (越界错误)
│   └── future_error (future错误,C++11)
├── runtime_error (运行时错误 - 运行时才能检测)
│   ├── range_error (范围错误)
│   ├── overflow_error (溢出错误)
│   ├── underflow_error (下溢错误)
│   └── system_error (系统错误,C++11)
├── bad_alloc (内存分配失败)
├── bad_cast (dynamic_cast失败)
├── bad_typeid (typeid失败)
├── bad_exception (unexpected异常)
└── bad_function_call (空function调用,C++11)

17.2.2 各类异常详解

#include <iostream>
#include <stdexcept>
#include <vector>
#include <string>
using namespace std;

void demonstrateLogicErrors() {
    cout << "=== logic_error及其派生类 ===" << endl;

    // invalid_argument: 无效参数
    try {
        throw invalid_argument("这是一个无效的参数");
    } catch (const invalid_argument& e) {
        cout << "invalid_argument: " << e.what() << endl;
    }

    // out_of_range: 越界错误
    try {
        vector<int> vec = {1, 2, 3};
        vec.at(10) = 100;  // 抛出out_of_range
    } catch (const out_of_range& e) {
        cout << "out_of_range: " << e.what() << endl;
    }

    // length_error: 长度错误
    try {
        string s;
        s.resize(s.max_size() + 1);  // 超过最大长度
    } catch (const length_error& e) {
        cout << "length_error: " << e.what() << endl;
    }
}

void demonstrateRuntimeErrors() {
    cout << "\n=== runtime_error及其派生类 ===" << endl;

    // runtime_error: 通用运行时错误
    try {
        throw runtime_error("运行时发生错误");
    } catch (const runtime_error& e) {
        cout << "runtime_error: " << e.what() << endl;
    }

    // overflow_error: 溢出错误
    try {
        throw overflow_error("数值溢出");
    } catch (const overflow_error& e) {
        cout << "overflow_error: " << e.what() << endl;
    }

    // underflow_error: 下溢错误
    try {
        throw underflow_error("数值下溢");
    } catch (const underflow_error& e) {
        cout << "underflow_error: " << e.what() << endl;
    }
}

void demonstrateMemoryErrors() {
    cout << "\n=== 内存相关异常 ===" << endl;

    // bad_alloc: 内存分配失败
    try {
        size_t huge = -1;  // 非常大的数
        int* ptr = new int[huge];  // 抛出bad_alloc
    } catch (const bad_alloc& e) {
        cout << "bad_alloc: " << e.what() << endl;
    }
}

int main() {
    demonstrateLogicErrors();
    demonstrateRuntimeErrors();
    demonstrateMemoryErrors();

    return 0;
}

17.2.3 自定义异常类的最佳实践

#include <iostream>
#include <exception>
#include <string>
using namespace std;

// 方式1:继承std::exception
class MyException : public exception {
private:
    string message;

public:
    explicit MyException(const string& msg) : message(msg) {}

    const char* what() const noexcept override {
        return message.c_str();
    }
};

// 方式2:继承std::runtime_error(推荐)
class FileException : public runtime_error {
private:
    string filename;

public:
    FileException(const string& msg, const string& file)
        : runtime_error(msg), filename(file) {}

    const string& getFilename() const { return filename; }
};

// 方式3:异常类层次
class NetworkException : public runtime_error {
public:
    using runtime_error::runtime_error;
};

class ConnectionException : public NetworkException {
public:
    using NetworkException::NetworkException;
};

class TimeoutException : public NetworkException {
public:
    using NetworkException::NetworkException;
};

void testCustomExceptions() {
    // 测试MyException
    try {
        throw MyException("自定义异常发生");
    } catch (const MyException& e) {
        cout << "捕获:" << e.what() << endl;
    }

    // 测试FileException
    try {
        throw FileException("文件打开失败", "data.txt");
    } catch (const FileException& e) {
        cout << "捕获:" << e.what()
             << ", 文件:" << e.getFilename() << endl;
    }

    // 测试异常类层次
    try {
        throw TimeoutException("连接超时");
    } catch (const TimeoutException& e) {
        cout << "超时异常:" << e.what() << endl;
    } catch (const NetworkException& e) {
        cout << "网络异常:" << e.what() << endl;
    }
}

int main() {
    testCustomExceptions();
    return 0;
}

17.3 异常捕获的高级用法

17.3.1 多重catch块的顺序

#include <iostream>
#include <stdexcept>
using namespace std;

void demonstrateCatchOrder() {
    try {
        throw out_of_range("越界错误");
    }
    catch (const out_of_range& e) {
        // 具体异常应该放在前面
        cout << "捕获out_of_range: " << e.what() << endl;
    }
    catch (const logic_error& e) {
        // 基类异常放在后面
        cout << "捕获logic_error: " << e.what() << endl;
    }
    catch (const exception& e) {
        // 最通用的异常放在最后
        cout << "捕获exception: " << e.what() << endl;
    }
}

int main() {
    demonstrateCatchOrder();
    return 0;
}

重要规则:

  • 派生类异常必须在基类异常之前捕获
  • 否则派生类的catch块永远不会被执行

17.3.2 捕获所有异常

#include <iostream>
using namespace std;

void riskyFunction() {
    throw 42;  // 抛出int类型异常
}

int main() {
    try {
        riskyFunction();
    }
    catch (const exception& e) {
        cout << "标准异常:" << e.what() << endl;
    }
    catch (...) {
        // 捕获所有类型的异常
        cout << "捕获未知类型异常" << endl;
    }

    return 0;
}

17.3.3 重新抛出异常

#include <iostream>
#include <stdexcept>
using namespace std;

void innerFunction() {
    throw runtime_error("内部错误");
}

void middleFunction() {
    try {
        innerFunction();
    } catch (const exception& e) {
        cout << "middleFunction捕获: " << e.what() << endl;
        // 重新抛出原异常
        throw;
    }
}

void outerFunction() {
    try {
        middleFunction();
    } catch (const exception& e) {
        cout << "outerFunction捕获: " << e.what() << endl;
    }
}

int main() {
    outerFunction();
    return 0;
}

throw vs throw e的区别:

try {
    // ...
} catch (const exception& e) {
    throw;    // ✅ 正确:重新抛出原始异常,保留类型信息
    // throw e;  // ❌ 不好:会对象切片,丢失派生类信息
}

17.3.4 嵌套异常(C++11)

#include <iostream>
#include <exception>
#include <stdexcept>
using namespace std;

void processFile(const string& filename) {
    try {
        throw runtime_error("文件读取失败");
    } catch (...) {
        // 抛出新异常,同时保留原异常
        throw_with_nested(logic_error("处理文件时出错: " + filename));
    }
}

void printException(const exception& e, int level = 0) {
    cout << string(level, ' ') << "异常: " << e.what() << endl;

    try {
        rethrow_if_nested(e);
    } catch (const exception& nested) {
        printException(nested, level + 2);
    }
}

int main() {
    try {
        processFile("data.txt");
    } catch (const exception& e) {
        printException(e);
    }

    return 0;
}

17.4 异常安全性保证

17.4.1 异常安全性的三个级别

#include <iostream>
#include <vector>
#include <string>
#include <memory>
using namespace std;

// 1. 基本保证(Basic Guarantee)
// - 不会泄漏资源
// - 对象处于有效状态(但可能不是原始状态)
class BasicGuarantee {
private:
    vector<int> data;
    int count;

public:
    void add(int value) {
        data.push_back(value);  // 可能抛出异常
        count++;                // 如果上面抛异常,count没有增加
    }
    // 问题:data和count可能不一致
};

// 2. 强保证(Strong Guarantee)
// - 操作成功或失败
// - 失败时状态完全不变
class StrongGuarantee {
private:
    vector<int> data;
    int count;

public:
    void add(int value) {
        auto temp = data;       // 先复制
        temp.push_back(value);  // 在副本上操作
        data = move(temp);      // 只有成功才修改
        count++;
    }
    // 保证:要么成功,要么状态完全不变
};

// 3. 不抛异常保证(Nothrow Guarantee)
// - 保证不会抛出异常
class NothrowGuarantee {
private:
    int* ptr;

public:
    NothrowGuarantee() : ptr(nullptr) {}

    ~NothrowGuarantee() noexcept {
        delete ptr;  // 析构函数应该noexcept
    }

    void swap(NothrowGuarantee& other) noexcept {
        std::swap(ptr, other.ptr);  // swap通常不抛异常
    }
};

17.4.2 RAII与异常安全

#include <iostream>
#include <fstream>
#include <memory>
#include <mutex>
using namespace std;

// ❌ 不安全的代码
void unsafeFunction() {
    int* ptr = new int[100];
    // 如果这里抛出异常,内存泄漏!
    if (/* 某个条件 */ false) {
        throw runtime_error("错误");
    }
    delete[] ptr;
}

// ✅ 使用RAII的安全代码
void safeFunction() {
    unique_ptr<int[]> ptr(new int[100]);
    // 即使抛出异常,unique_ptr也会自动释放内存
    if (/* 某个条件 */ false) {
        throw runtime_error("错误");
    }
}

// RAII封装文件操作
class FileHandler {
private:
    ifstream file;
    string filename;

public:
    FileHandler(const string& name) : filename(name) {
        file.open(filename);
        if (!file.is_open()) {
            throw runtime_error("无法打开文件: " + filename);
        }
    }

    ~FileHandler() {
        if (file.is_open()) {
            file.close();
        }
    }

    string readLine() {
        string line;
        if (!getline(file, line)) {
            throw runtime_error("读取失败");
        }
        return line;
    }
};

// RAII封装互斥锁
void threadSafeFunction(mutex& mtx, int& shared_data) {
    lock_guard<mutex> lock(mtx);  // RAII管理锁
    // 即使抛出异常,锁也会自动释放
    shared_data++;
    if (shared_data > 100) {
        throw runtime_error("数据超限");
    }
}

int main() {
    try {
        safeFunction();

        FileHandler fh("data.txt");
        cout << fh.readLine() << endl;
    } catch (const exception& e) {
        cout << "错误: " << e.what() << endl;
    }

    return 0;
}

17.4.3 Copy-and-Swap惯用法

#include <iostream>
#include <algorithm>
using namespace std;

class SafeClass {
private:
    int* data;
    size_t size;

public:
    SafeClass(size_t s) : data(new int[s]), size(s) {}

    SafeClass(const SafeClass& other)
        : data(new int[other.size]), size(other.size) {
        copy(other.data, other.data + size, data);
    }

    ~SafeClass() {
        delete[] data;
    }

    // 使用Copy-and-Swap实现强异常安全保证
    SafeClass& operator=(const SafeClass& other) {
        SafeClass temp(other);  // 先复制(可能抛异常)
        swap(temp);             // 交换(不抛异常)
        return *this;           // temp析构时释放旧数据
    }

    void swap(SafeClass& other) noexcept {
        std::swap(data, other.data);
        std::swap(size, other.size);
    }

    void print() const {
        for (size_t i = 0; i < size; ++i) {
            cout << data[i] << " ";
        }
        cout << endl;
    }
};

int main() {
    SafeClass obj1(5);
    SafeClass obj2(3);

    obj1 = obj2;  // 强异常安全:要么成功,要么obj1不变

    return 0;
}

17.5 函数try块

17.5.1 构造函数的函数try块

#include <iostream>
#include <stdexcept>
using namespace std;

class Resource {
public:
    Resource() {
        cout << "Resource构造" << endl;
        throw runtime_error("Resource构造失败");
    }

    ~Resource() {
        cout << "Resource析构" << endl;
    }
};

class MyClass {
private:
    Resource res;
    int value;

public:
    // 函数try块:捕获初始化列表中的异常
    MyClass(int v)
    try : res(), value(v) {
        cout << "MyClass构造函数体" << endl;
    }
    catch (const exception& e) {
        cout << "捕获初始化异常: " << e.what() << endl;
        // 注意:这里会自动重新抛出异常
        // 不能阻止异常传播
    }
};

int main() {
    try {
        MyClass obj(10);
    } catch (const exception& e) {
        cout << "外部捕获: " << e.what() << endl;
    }

    return 0;
}

重要提示:

  • 构造函数的函数try块会自动重新抛出异常
  • 主要用于记录日志或清理资源
  • 不能完全阻止异常传播

17.5.2 普通函数的函数try块

#include <iostream>
using namespace std;

int divide(int a, int b)
try {
    if (b == 0) {
        throw invalid_argument("除数为零");
    }
    return a / b;
}
catch (const exception& e) {
    cout << "函数try块捕获: " << e.what() << endl;
    return 0;  // 可以返回默认值
}

int main() {
    cout << divide(10, 2) << endl;  // 5
    cout << divide(10, 0) << endl;  // 0

    return 0;
}

17.6 noexcept说明符详解

17.6.1 基本用法

#include <iostream>
using namespace std;

// 声明不会抛出异常
void safeFunc() noexcept {
    // 这个函数保证不抛异常
    cout << "安全函数" << endl;
}

// 条件noexcept
template<typename T>
void conditionalFunc(T value) noexcept(noexcept(value.print())) {
    value.print();
}

int main() {
    safeFunc();

    // 检查函数是否noexcept
    cout << "safeFunc是noexcept: "
         << noexcept(safeFunc()) << endl;  // 1 (true)

    return 0;
}

17.6.2 noexcept与移动语义

#include <iostream>
#include <vector>
using namespace std;

class MyClass {
public:
    MyClass() { cout << "构造" << endl; }

    // 移动构造应该声明为noexcept
    MyClass(MyClass&&) noexcept {
        cout << "移动构造" << endl;
    }

    // 拷贝构造
    MyClass(const MyClass&) {
        cout << "拷贝构造" << endl;
    }
};

int main() {
    vector<MyClass> vec;
    vec.reserve(2);

    vec.push_back(MyClass());  // 第一个元素

    cout << "添加第二个元素(可能触发扩容):" << endl;
    vec.push_back(MyClass());  // 扩容时会使用移动构造

    return 0;
}

重要:

  • vector扩容时,如果移动构造是noexcept,使用移动
  • 否则使用拷贝(为了异常安全)

17.6.3 析构函数与noexcept

class MyClass {
public:
    // ✅ 析构函数默认是noexcept
    ~MyClass() {
        // 不要在析构函数中抛出异常
    }

    // ❌ 不要这样做
    ~MyClass() noexcept(false) {
        throw runtime_error("析构函数抛异常");
        // 危险!可能导致程序终止
    }
};

规则:

  • 析构函数默认是noexcept(true)
  • 永远不要在析构函数中抛出异常

17.7 异常与性能

17.7.1 异常的开销

#include <iostream>
#include <chrono>
using namespace std;
using namespace chrono;

// 方法1:使用异常
int divideWithException(int a, int b) {
    if (b == 0) {
        throw invalid_argument("除数为零");
    }
    return a / b;
}

// 方法2:使用错误码
int divideWithErrorCode(int a, int b, bool& success) {
    if (b == 0) {
        success = false;
        return 0;
    }
    success = true;
    return a / b;
}

void benchmarkException() {
    auto start = high_resolution_clock::now();

    int result = 0;
    for (int i = 0; i < 1000000; ++i) {
        try {
            result += divideWithException(10, 2);
        } catch (...) {
            // 不会执行
        }
    }

    auto end = high_resolution_clock::now();
    auto duration = duration_cast<microseconds>(end - start);

    cout << "异常方式(无异常)耗时: " << duration.count() << " 微秒" << endl;
}

void benchmarkErrorCode() {
    auto start = high_resolution_clock::now();

    int result = 0;
    bool success;
    for (int i = 0; i < 1000000; ++i) {
        result += divideWithErrorCode(10, 2, success);
    }

    auto end = high_resolution_clock::now();
    auto duration = duration_cast<microseconds>(end - start);

    cout << "错误码方式耗时: " << duration.count() << " 微秒" << endl;
}

int main() {
    benchmarkException();
    benchmarkErrorCode();

    return 0;
}

性能建议:

  • 正常路径无异常时,异常机制开销很小
  • 抛出异常时,开销较大
  • 不要将异常用于正常流程控制

17.7.2 异常vs错误码的选择

// ✅ 适合使用异常的场景
class File {
public:
    File(const string& filename) {
        // 构造失败无法返回错误码,使用异常
        if (!open(filename)) {
            throw runtime_error("打开文件失败");
        }
    }
};

// ✅ 适合使用错误码的场景
bool parseInteger(const string& str, int& result) {
    // 解析失败是常见情况,使用错误码
    try {
        result = stoi(str);
        return true;
    } catch (...) {
        return false;
    }
}

选择原则:

  1. 错误是异常情况 → 使用异常
  2. 错误是正常情况 → 使用错误码
  3. 无法通过返回值报告错误(构造函数) → 使用异常
  4. 需要跨越多层函数传播错误 → 使用异常
  5. 追求极致性能的关键路径 → 使用错误码

17.8 异常处理最佳实践

17.8.1 异常类设计原则

#include <iostream>
#include <exception>
#include <string>
using namespace std;

// ✅ 好的异常类设计
class DatabaseException : public runtime_error {
private:
    int errorCode;
    string sqlStatement;

public:
    DatabaseException(const string& msg, int code, const string& sql)
        : runtime_error(msg), errorCode(code), sqlStatement(sql) {}

    int getErrorCode() const { return errorCode; }
    const string& getSqlStatement() const { return sqlStatement; }

    // 提供详细的错误信息
    string getDetailedMessage() const {
        return string(what()) + " (错误码: " + to_string(errorCode) +
               ", SQL: " + sqlStatement + ")";
    }
};

void testDatabaseException() {
    try {
        throw DatabaseException("查询失败", 1064,
                               "SELECT * FROM users WHERE id = ?");
    } catch (const DatabaseException& e) {
        cout << e.getDetailedMessage() << endl;
    }
}

int main() {
    testDatabaseException();
    return 0;
}

17.8.2 异常安全的代码模式

#include <iostream>
#include <memory>
#include <vector>
using namespace std;

// 模式1:使用智能指针管理资源
void pattern1() {
    unique_ptr<int[]> data(new int[100]);
    // 自动管理,异常安全
}

// 模式2:在一个语句中只做一件事
void pattern2() {
    // ❌ 不好
    // processWidget(shared_ptr<Widget>(new Widget()), priority());
    // 如果priority()抛异常,Widget可能泄漏

    // ✅ 好
    shared_ptr<Widget> pw(new Widget());
    processWidget(pw, priority());
}

// 模式3:使用STL容器
void pattern3() {
    vector<int> vec;
    vec.push_back(1);  // 自动管理内存,异常安全
}

17.8.3 日志与异常

#include <iostream>
#include <fstream>
#include <string>
#include <ctime>
using namespace std;

class Logger {
private:
    ofstream logFile;

public:
    Logger(const string& filename) {
        logFile.open(filename, ios::app);
    }

    void log(const string& level, const string& message) {
        time_t now = time(nullptr);
        logFile << ctime(&now) << " [" << level << "] "
                << message << endl;
    }

    void logException(const exception& e) {
        log("ERROR", string("异常: ") + e.what());
    }
};

void businessLogic() {
    Logger logger("app.log");

    try {
        // 业务逻辑
        throw runtime_error("业务错误");
    } catch (const exception& e) {
        logger.logException(e);
        throw;  // 重新抛出以便上层处理
    }
}

int main() {
    try {
        businessLogic();
    } catch (const exception& e) {
        cout << "最终捕获: " << e.what() << endl;
    }

    return 0;
}

17.9 实战练习

练习1:实现安全的资源管理类

#include <iostream>
#include <fstream>
#include <string>
using namespace std;

class SafeFileReader {
private:
    ifstream file;
    string filename;

public:
    explicit SafeFileReader(const string& name) : filename(name) {
        file.open(filename);
        if (!file.is_open()) {
            throw runtime_error("无法打开文件: " + filename);
        }
    }

    ~SafeFileReader() {
        if (file.is_open()) {
            file.close();
        }
    }

    // 禁止拷贝
    SafeFileReader(const SafeFileReader&) = delete;
    SafeFileReader& operator=(const SafeFileReader&) = delete;

    string readLine() {
        string line;
        if (!getline(file, line)) {
            if (file.eof()) {
                throw runtime_error("文件结束");
            } else {
                throw runtime_error("读取错误");
            }
        }
        return line;
    }

    vector<string> readAll() {
        vector<string> lines;
        string line;
        while (getline(file, line)) {
            lines.push_back(line);
        }
        return lines;
    }
};

int main() {
    try {
        SafeFileReader reader("test.txt");
        auto lines = reader.readAll();

        for (const auto& line : lines) {
            cout << line << endl;
        }
    } catch (const exception& e) {
        cout << "错误: " << e.what() << endl;
    }

    return 0;
}

练习2:实现带重试机制的函数

#include <iostream>
#include <stdexcept>
#include <chrono>
#include <thread>
using namespace std;

template<typename Func>
auto retryOnFailure(Func func, int maxRetries = 3,
                   int delayMs = 100) -> decltype(func()) {
    for (int attempt = 0; attempt < maxRetries; ++attempt) {
        try {
            return func();
        } catch (const exception& e) {
            if (attempt == maxRetries - 1) {
                // 最后一次尝试失败,重新抛出
                throw;
            }

            cout << "尝试 " << (attempt + 1) << " 失败: "
                 << e.what() << ", 重试中..." << endl;

            // 等待后重试
            this_thread::sleep_for(chrono::milliseconds(delayMs));
        }
    }
}

// 模拟不稳定的网络请求
int unstableNetworkRequest() {
    static int callCount = 0;
    callCount++;

    if (callCount < 3) {
        throw runtime_error("网络连接失败");
    }

    return 200;  // 成功
}

int main() {
    try {
        int result = retryOnFailure(unstableNetworkRequest);
        cout << "请求成功,状态码: " << result << endl;
    } catch (const exception& e) {
        cout << "最终失败: " << e.what() << endl;
    }

    return 0;
}

练习3:实现异常安全的栈

#include <iostream>
#include <stdexcept>
#include <memory>
using namespace std;

template<typename T>
class SafeStack {
private:
    struct Node {
        T data;
        unique_ptr<Node> next;

        Node(const T& value) : data(value), next(nullptr) {}
    };

    unique_ptr<Node> head;
    size_t count;

public:
    SafeStack() : head(nullptr), count(0) {}

    void push(const T& value) {
        auto newNode = make_unique<Node>(value);
        newNode->next = move(head);
        head = move(newNode);
        count++;
    }

    T pop() {
        if (!head) {
            throw runtime_error("栈为空");
        }

        T value = head->data;
        head = move(head->next);
        count--;
        return value;
    }

    const T& top() const {
        if (!head) {
            throw runtime_error("栈为空");
        }
        return head->data;
    }

    bool empty() const {
        return head == nullptr;
    }

    size_t size() const {
        return count;
    }
};

int main() {
    try {
        SafeStack<int> stack;

        stack.push(1);
        stack.push(2);
        stack.push(3);

        while (!stack.empty()) {
            cout << stack.pop() << " ";
        }
        cout << endl;

        // stack.pop();  // 抛出异常

    } catch (const exception& e) {
        cout << "错误: " << e.what() << endl;
    }

    return 0;
}

参考资料

  1. 书籍

    • Stanley B. Lippman. 《C++ Primer》(第5版) - 第18章 异常处理
    • Bjarne Stroustrup. 《C++程序设计语言》(第4版) - 异常处理
    • Scott Meyers. 《More Effective C++》 - 条款9-15 异常
    • Herb Sutter. 《Exceptional C++》 - 异常安全性
  2. 在线文档

  3. 核心概念

  4. 技术文章

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐