异常处理与动态存储空间分配

异常处理与动态存储空间分配

内存动态分配和释放

  1. 动态分配

    • 使用 new 分配单个对象,如 int* y = new int;
    • 使用 new[] 分配数组,如 int* x = new int[9];
    • 使用 new 分配二维数组的指针数组和每行的数组,如 x = new G* [NumberOfRow];x[i] = new G[NumberOfColumns];
  2. 内存释放

    • 使用 delete 释放单个对象,如 delete y;
    • 使用 delete[] 释放数组,如 delete[] x;
    • 使用循环释放二维数组的每行,然后释放指针数组,如:
      for(int i = 0; i < NumberOfRow; i++)
          delete[] x[i];
      delete[] x;
      

异常处理

  1. try:将可能抛出异常的代码放入 try 块中,如:

    try {
        t = new float[n];
    }
    
  2. catch:捕获并处理异常,如:

    catch (const std::bad_alloc&) {
        std::cerr << "Out of memory" << endl;
        exit(1);
    }
    
  3. 多类型异常处理:可以捕获不同类型的异常,如:

    catch (const char* e) {
        cout << "Caught exception: " << e << endl;
    }
    catch (const std::exception& e) {
        cout << "Caught exception: " << e.what() << endl;
    }
    catch (...) {
        cout << "Caught unknown exception" << endl;
    }
    

在C++中,动态建立和删除二维数组需要对内存进行手动管理。下面详细讲解代码中动态建立和删除二维数组的过程。

动态建立二维数组

在代码中,make2dArray模板函数用于动态分配一个二维数组。以下是这个函数的详细讲解:

template<class G>
bool make2dArray(G** &x, int NumberOfRow, int NumberOfColumns){
    try {
        // 分配一个包含 NumberOfRow 个元素的指针数组,每个元素都是指向 G 类型的指针
        x = new G* [NumberOfRow];
        for(int i = 0; i < NumberOfRow; i++) {
            // 为每个指针分配一个包含 NumberOfColumns 个 G 类型元素的数组
            x[i] = new G [NumberOfColumns];
        }
        return true; // 如果成功分配,返回 true
    } catch (const std::bad_alloc&) {
        return false; // 如果内存分配失败,捕获异常并返回 false
    }
}
详细步骤:
  1. 声明指针数组

    x = new G*[NumberOfRow];
    

    这里的 x 是一个指向指针的引用,通过 new 操作符动态分配一个包含 NumberOfRow 个元素的指针数组。每个元素都是指向 G 类型的指针。

  2. 分配每行的数组

    for(int i = 0; i < NumberOfRow; i++) {
        x[i] = new G[NumberOfColumns];
    }
    

    使用循环遍历指针数组,为每个指针分配一个包含 NumberOfColumnsG 类型元素的数组。

  3. 异常处理

    catch (const std::bad_alloc&) {
        return false;
    }
    

    如果在分配内存的过程中发生异常(如内存不足),捕获 std::bad_alloc 异常并返回 false

删除二维数组

在代码中,delete2dArray模板函数用于释放动态分配的二维数组。以下是这个函数的详细讲解:

template<class G>
void delete2dArray(G** &x, int NumberOfRow){
    for(int i = 0; i < NumberOfRow; i++) {
        // 释放每行的数组
        delete[] x[i];
    }
    // 释放指针数组
    delete[] x;
    // 将指针置为 NULL,避免悬空指针
    x = NULL;
}
详细步骤:
  1. 释放每行的数组

    for(int i = 0; i < NumberOfRow; i++) {
        delete[] x[i];
    }
    

    使用循环遍历指针数组,释放每个指针指向的数组内存。

  2. 释放指针数组

    delete[] x;
    

    释放指针数组本身的内存。

  3. 防止悬空指针

    x = NULL;
    

    将指针 x 置为 NULL,以避免悬空指针。

main 函数中的调用

以下是 main 函数中动态分配和删除二维数组的部分:

int r = 5, c = 5; // 假设初始化 r 和 c 为 5
int** p; // 定义一个指向指针的指针
try {
    if (!make2dArray(p, r, c)) { // 动态分配一个 r 行 c 列的二维数组
        std::cerr << "cannot make p" << endl; // 输出错误信息
        exit(1); // 退出程序
    }
} catch (const std::bad_alloc&) { // 捕获内存分配失败的异常
    std::cerr << "cannot make p" << endl; // 输出错误信息
    exit(1); // 退出程序
}

// 释放动态分配的二维数组的内存
delete2dArray(p, r);
详细步骤:
  1. 动态分配二维数组

    if (!make2dArray(p, r, c)) {
        std::cerr << "cannot make p" << endl;
        exit(1);
    }
    

    调用 make2dArray 函数为指针 p 动态分配一个 rc 列的二维数组。如果分配失败,输出错误信息并退出程序。

  2. 释放二维数组内存

    delete2dArray(p, r);
    

    调用 delete2dArray 函数释放指针 p 指向的二维数组的内存。

总结

  • 动态建立二维数组:使用 new 操作符分配指针数组和每行的数组,并处理内存分配失败的异常。
  • 释放二维数组内存:使用 delete[] 操作符释放每行的数组和指针数组,并将指针置为 NULL 以防止悬空指针。
  • 异常处理:使用 try-catch 块捕获和处理内存分配失败的异常,确保程序在内存不足时能够正确处理并输出错误信息。

代码示例

#include <iostream>
using std::cout;
using std::endl;

// 定义一个模板函数 abc,接受三个相同类型的参数,返回 a + b * c 的结果
template<class T>
T abc(T a, T b, T c){
    return a + b * c;
}

// 定义一个模板函数 bcd,接受三个不同类型的参数,返回 a + b * c 的结果
template<class Ta, class Tb, class Tc>
Ta bcd(const Ta& a, const Tb& b, const Tc& c){
    return a + b * c;
}

// 定义一个模板函数 make2dArray,动态创建一个二维数组并返回成功与否
template<class G>
bool make2dArray(G** &x, int NumberOfRow, int NumberOfColumns){
    try {
        x = new G* [NumberOfRow]; // 分配指针数组,每个指针指向一行
        for(int i = 0; i < NumberOfRow; i++)
            x[i] = new G [NumberOfColumns]; // 分配每行的数组
        return true; // 成功分配返回 true
    } catch (const std::bad_alloc&) { // 捕获内存分配失败的异常
        return false; // 分配失败返回 false
    }
}

// 定义一个模板函数 delete2dArray,释放动态分配的二维数组
template<class G>
void delete2dArray(G** &x, int NumberOfRow){
    for(int i = 0; i < NumberOfRow; i++)
        delete[] x[i]; // 释放每行的内存
    delete[] x; // 释放指针数组的内存
    x = NULL; // 将指针置为 NULL,避免悬空指针
}

// 定义一个函数 cde,如果参数 <= 0,则抛出异常;否则返回 a + b * c 的结果
int cde(int a, int b, int c){
    if(a <= 0 || b <= 0 || c <= 0)
        throw "All parameters should be > 0"; // 抛出 const char* 类型的异常
    return a + b * c;
}

int main() {
    try {
        // 调用模板函数 abc,输出结果
        cout << abc(1, 2, 3) << endl; // 输出 7
        // 调用模板函数 bcd,输出结果
        cout << bcd(1, 2.35, 3.10e-2) << endl; // 输出 1.07285
        // 调用函数 cde,输出结果(会抛出异常)
        cout << cde(-3, 2, 8) << endl;
    } catch (const char* e) { // 捕获 const char* 类型的异常
        cout << "Caught exception: " << e << endl; // 输出异常信息
    } catch (const std::exception& e) { // 捕获 std::exception 类型的异常
        cout << "Caught exception: " << e.what() << endl; // 输出异常信息
    } catch (...) { // 捕获所有其他类型的异常
        cout << "Caught unknown exception" << endl; // 输出未知异常信息
    }

    try {
        // 再次调用函数 cde,输出结果(会抛出异常)
        cout << cde(4, 3, -1) << endl;
    } catch (const char* e) { // 捕获 const char* 类型的异常
        cout << "throw " << e << endl; // 输出异常信息
    }

    int* y = new int; // 动态分配一个 int 型变量
    *y = 10; // 将 y 指向的值设为 10
    int* x = new int[9]; // 动态分配一个包含 9 个 int 的数组
    cout << y << " " << *y << endl; // 输出 y 的地址和值
    cout << x << " " << *x << endl; // 输出 x 的地址和第一个元素的值
    delete y; // 释放动态分配的单个 int 变量的内存
    delete[] x; // 释放动态分配的 int 数组的内存

    int n = 10; // 初始化 n 为 10
    float* z = new float[n]; // 动态分配一个包含 n 个 float 的数组
    float* t;
    try {
        t = new float[n]; // 动态分配一个包含 n 个 float 的数组
    } catch (const std::bad_alloc&) { // 捕获内存分配失败的异常
       std::cerr << "Out of memory" << endl; // 输出错误信息
       exit(1); // 退出程序
    }

    char(*h)[5]; // 定义一个指向包含 5 个 char 的数组的指针
    try {
        h = new char[n][5]; // 动态分配一个 n 行 5 列的二维 char 数组
    } catch (const std::bad_alloc&) { // 捕获内存分配失败的异常
        std::cerr << "out of memory" << endl; // 输出错误信息
        exit(1); // 退出程序
    }

    int r = 5, c = 5; // 初始化 r 和 c 为 5
    int** p; // 定义一个指向指针的指针
    try {
        if (!make2dArray(p, r, c)) { // 动态分配一个 r 行 c 列的二维数组
            std::cerr << "cannot make p" << endl; // 输出错误信息
            exit(1); // 退出程序
        }
    } catch (const std::bad_alloc&) { // 捕获内存分配失败的异常
        std::cerr << "cannot make p" << endl; // 输出错误信息
        exit(1); // 退出程序
    }
    delete2dArray(p, r); // 释放动态分配的二维数组的内存
    // 释放 z 和 t
    delete[] z; // 释放动态分配的 float 数组 z 的内存
    delete[] t; // 释放动态分配的 float 数组 t 的内存

    // 释放 h
    delete[] h; // 释放动态分配的二维 char 数组 h 的内存

    return 0;
}
  • 22
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值