C++ 内存分配并尝试捕获块

C++ 内存分配并尝试捕获块,c++,memory-management,C++,Memory Management,我有一个分配2D数组的函数,以便不消耗超过我需要的内存: _> 模板Xvar**New2(无符号整数行、无符号整数列) { Xvar**mem; 无符号整数大小,i; 大小=行*列; mem=新的Xvar*[行]; mem[0]=新的Xvar[size]; 对于(i=1;i,在第二种方式中,如果第一个new失败,则计算立即跳转到catch块,甚至从未尝试访问mem[0] 在任何情况下,如果您希望允许分配失败并容易地检测到这一点,您可能应该使用nothrow变量,如果分配失败,它只会返回NULL

我有一个分配2D数组的函数,以便不消耗超过我需要的内存:

_>

模板Xvar**New2(无符号整数行、无符号整数列)
{
Xvar**mem;
无符号整数大小,i;
大小=行*列;
mem=新的Xvar*[行];
mem[0]=新的Xvar[size];

对于(i=1;i,在第二种方式中,如果第一个
new
失败,则计算立即跳转到catch块,甚至从未尝试访问
mem[0]

在任何情况下,如果您希望允许分配失败并容易地检测到这一点,您可能应该使用
nothrow
变量,如果分配失败,它只会返回
NULL

mem = new (nothrow) Xvar*[rows];
if (!mem) {
    // allocation failed, do whatever you want
}
mem[0] = new (nothrow) Xvar[size];
if (!mem[0]) {
    // allocation failed, do whatever you want
}

第二种方法是,如果第一个
new
失败,则求值立即跳转到catch块,甚至从不尝试访问
mem[0]

在任何情况下,如果您希望允许分配失败并容易地检测到这一点,您可能应该使用
nothrow
变量,如果分配失败,它只会返回
NULL

mem = new (nothrow) Xvar*[rows];
if (!mem) {
    // allocation failed, do whatever you want
}
mem[0] = new (nothrow) Xvar[size];
if (!mem[0]) {
    // allocation failed, do whatever you want
}

根本不捕获异常,只需在函数展开时使用RAII清理内存:

template <class Xvar> Xvar** New2 (unsigned int rows,unsigned int cols)
{
    unsigned int size = rows * cols;
    std::unique_ptr<Xvar*[]> mem(new Xvar* [rows]);
    mem[0] = new Xvar [size];
    for (i=1; i<rows; i++)
        mem[i] = &mem[0][i*cols];
    return mem.release();
}
易碎且令人不快。有两种更好的设计:

  • 使用一个真正的矩阵/2d数组模板类来管理存储,并且可以通过值返回。然后,当这个值对象超出范围时,将回收内存

  • 使用带有自定义删除器的智能指针

    template <typename T> struct 2dDelete
    {
        void operator() (T **rows) {
            delete [] rows[0];
            delete [] rows;
        }
    };
    
    template <typename T>
    std::unique_ptr<T*[], 2dDelete<T>> 2dNew (unsigned rows, unsigned cols)
    {
        unsigned size = rows * cols;
        std::unique_ptr<Xvar*[]> tmp(new Xvar* [rows]);
        tmp[0] = new Xvar [size];
        for (i=1; i<rows; i++)
            tmp[i] = &tmp[0][i*cols];
        // hand-over from the intermediate pointer (which only owned the
        // top-level row allocation) to the caller's pointer (which will
        // own, and clean up, the whole thing).
        return std::unique_ptr<T*[], 2dDelete<T>> arr(mem.release());
    }
    
    模板结构2dDelete
    {
    void运算符()(T**行){
    删除[]行[0];
    删除[]行;
    }
    };
    模板
    std::unique_ptr 2dNew(无符号行、无符号列)
    {
    无符号大小=行*列;
    std::unique_ptr tmp(新的Xvar*[rows]);
    tmp[0]=新的Xvar[size];
    
    对于(i=1;i根本不捕获异常,只需在函数展开时使用RAII清理内存即可:

    template <class Xvar> Xvar** New2 (unsigned int rows,unsigned int cols)
    {
        unsigned int size = rows * cols;
        std::unique_ptr<Xvar*[]> mem(new Xvar* [rows]);
        mem[0] = new Xvar [size];
        for (i=1; i<rows; i++)
            mem[i] = &mem[0][i*cols];
        return mem.release();
    }
    
    易碎且令人不快。有两种更好的设计:

  • 使用一个真正的矩阵/2d数组模板类来管理存储,并且可以通过值返回。然后,当这个值对象超出范围时,将回收内存

  • 使用带有自定义删除器的智能指针

    template <typename T> struct 2dDelete
    {
        void operator() (T **rows) {
            delete [] rows[0];
            delete [] rows;
        }
    };
    
    template <typename T>
    std::unique_ptr<T*[], 2dDelete<T>> 2dNew (unsigned rows, unsigned cols)
    {
        unsigned size = rows * cols;
        std::unique_ptr<Xvar*[]> tmp(new Xvar* [rows]);
        tmp[0] = new Xvar [size];
        for (i=1; i<rows; i++)
            tmp[i] = &tmp[0][i*cols];
        // hand-over from the intermediate pointer (which only owned the
        // top-level row allocation) to the caller's pointer (which will
        // own, and clean up, the whole thing).
        return std::unique_ptr<T*[], 2dDelete<T>> arr(mem.release());
    }
    
    模板结构2dDelete
    {
    void运算符()(T**行){
    删除[]行[0];
    删除[]行;
    }
    };
    模板
    std::unique_ptr 2dNew(无符号行、无符号列)
    {
    无符号大小=行*列;
    std::unique_ptr tmp(新的Xvar*[rows]);
    tmp[0]=新的Xvar[size];
    
    对于(i=1;i1)如果
    new
    失败,
    mem没有任何意义,因为它超出了范围,因为
    new`在失败时会抛出一个异常(我想你知道这一点是因为你试图捕获它)。2)如果你不能对异常执行任何操作,那么捕获异常有什么意义使用<代码> STD::向量 4)在你的代码工作之前,不要担心性能。这里你可以:<代码> int(){{} /Case>世界上最快的托管C++程序!让你在任何地方都能找到你?你在“代码>新< /COD>失败之后怎么做?”Victor Ruiz:当你说“第二种方法不被推荐”时,你指的是“基于try-catch的第二个解决方案”或“问题的第二个代码示例”(这是基于try-catch的第一个解决方案)?现在,我明白了,我很傻。但是如果我想知道什么新的失败了,第一个还是第二个,我应该使用第一个解决方案还是第二个解决方案?1)如果
    new
    失败了,
    mem什么都不是,因为它超出了范围,因为
    new`失败时会抛出一个异常(我想,你知道这是因为你试图捕捉它).2)如果无法处理异常,捕获异常有什么意义?3)使用
    std::vector
    4)在代码正常工作之前,不要担心性能问题。给你:
    int main(){}<代码>世界上最快的托管C++程序!让你在哪里?在<代码>新< <代码>失败后你打算做什么?@ Victor Ruiz:当你说“第二种方法不推荐”时,你指的是“基于TestCcatch的第二个解决方案”还是“来自问题的第二个代码示例”(这是你基于TestCcatch的第一个解决方案)现在,我明白了,我很傻。但是如果我想知道什么新方法失败了,第一个还是第二个,我应该使用第一个解决方案还是第二个解决方案?我应该使用“nothrow”还是“nothrow”@VictorRuiz:use
    (nothrow)
    (nothrow)
    是我已经更正过的错误。我应该使用“nothrow”还是“nothrow”@VictorRuiz:use
    (nothrow)
    (禁止抛出)
    是一个我已经纠正过的错误。当然,人们应该在任何地方都应用它,包括内部分配和返回类型。无论如何,返回类型(我只是坚持OP的原型)。如果内部分配抛出,则它从未被分配,因此这不会泄漏。如果没有人对其调用
    delete
    ,则可以。最好将其打包,不要担心。如果
    new
    抛出
    bad\u alloc
    ,则有什么要删除的?如果相反,一个
    Xvar
    默认构造函数抛出,编译器仍负责c我说的是这一行
    mem[0]=new Xvar[size];
    。假设你拿出
    mem.release()
    行;删除什么
    mem[0]
    ?当然,你应该在任何地方都应用它,包括内部分配和返回类型。无论如何,返回类型(我只是坚持使用OP的原型)。如果内部分配抛出,则它从未被分配,因此这不会泄漏。如果没有人对其调用
    delete
    ,则可以。最好将其打包,不要担心。如果
    new
    抛出
    bad\u alloc
    ,则有什么要删除的?如果相反,一个
    Xvar
    默认构造函数抛出,编译器仍负责c向上倾斜。我说的是这一行
    mem[0]=new Xvar[size];
    。假设您取出
    mem.release()
    行;删除
    mem的内容
    
    template <typename T> struct 2dDelete
    {
        void operator() (T **rows) {
            delete [] rows[0];
            delete [] rows;
        }
    };
    
    template <typename T>
    std::unique_ptr<T*[], 2dDelete<T>> 2dNew (unsigned rows, unsigned cols)
    {
        unsigned size = rows * cols;
        std::unique_ptr<Xvar*[]> tmp(new Xvar* [rows]);
        tmp[0] = new Xvar [size];
        for (i=1; i<rows; i++)
            tmp[i] = &tmp[0][i*cols];
        // hand-over from the intermediate pointer (which only owned the
        // top-level row allocation) to the caller's pointer (which will
        // own, and clean up, the whole thing).
        return std::unique_ptr<T*[], 2dDelete<T>> arr(mem.release());
    }