C++ 内存分配并尝试捕获块
我有一个分配2D数组的函数,以便不消耗超过我需要的内存: _>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
模板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());
}