C++ 返回异常,我应该释放资源吗?
C++ Returning exception, Should I free resources?
我为我的构造函数编写了以下实现:
template<class T>
Matrix<T>::Matrix(const Dimensions &matrix_dimensions, const T &initial_value) : dimensions(matrix_dimensions),
data(new T[size()]) {
if (matrix_dimensions.getRow() <= 0 || matrix_dimensions.getCol() <= 0) {
return IllegalInitialization();
}
int matrix_size = size();
for (int i = 0; i < matrix_size; ++i) {
data[i] = initial_value;
}
}
因此,如果发生错误,我将返回IllegalInitialization()
缓存,但是我使用new分配的资源呢? 如何在返回之前释放它们,我应该叫删除吗?
只是一个旁注:我是这个领域的新手,所以有人可以检查上面的代码是否写得很好(性能明智,理论上按预期工作(
假设你的意思是throw
而不是return
(你不能从构造函数返回值!(,以便取消对象的创建,是的,你必须先delete[] data
。
通常的方法是递归应用"资源获取正在初始化"模式。也就是说,data
的类型不应该是原始指针,而应该是一些智能类型(如std::unique_ptr<T[]>
(,当它超出范围时会自动执行此删除。
(反过来,std::unique_ptr
内部是异常安全的。
如果你确实只是早return
,那么你就有更大的问题——对象处于无用状态,而拥有范围不知道它,并且你使用return
参数构建失败(因为,再次,你不能从构造函数返回值!
首先,问题中的代码永远不会编译,因为构造函数不能返回值。 因此,构造函数中return IllegalInitialization();
的语句是可诊断的错误。
为了这个答案的目的,我假设你实际上使用了throw IllegalInitialization();
其次,所示代码可能存在泄漏。data
是用new
表达式初始化的,因此data
的类型必须是指向与T
兼容的类型的指针(例如,指向T
基的指针(,或者它必须是具有接受此类指针的构造函数的类类型(例如std::unique_ptr<T>
(。 如果data
属于任何其他类型(例如int
,double
( 那么data
的初始化是一个可诊断的错误,因为(例如(指针不能隐式转换为int
。
如果data
是原始指针,则在构造函数中引发异常将导致泄漏。 不会释放使用new
表达式分配的对象或数据。
如果data
是一个类,其构造函数接受指针,则有两种可能性(代码将编译,并且没有未定义的行为(。
- 类构造函数保存指针,析构函数释放它(使用
delete []
,因为它对应于new
表达式(,然后动态分配的数据将被安全地释放。 此类的一个示例是类型std::unique_ptr<T[]>
。 这是代码可以避免泄漏的唯一情况。 - 否则,将出现内存泄漏。 即使
Matrix<T>
的析构函数清理了data
,在构造函数主体中抛出异常的行为也会阻止调用Matrix<T>
的析构函数(析构函数只能为已完全构造的对象调用 - 这意味着构造函数已完成而没有抛出异常(。
(还有其他情况,例如data
是一个具有析构函数的类的实例,该类使用错误的delete
表达式形式,但这些情况要么给出未定义的行为,要么以其他方式泄漏,所以我将忽略它们(。
第三(这更主观(,您使用Dimensions
类型(可能包含一对整数值(来表示矩阵维度。 本质上,你有一个要求,在Matrix
,维度是正的。 由于如果维度为非正值,则会抛出异常,因此我建议由Dimensions
类进行检查(例如,如果给定非正值,构造函数会抛出,则抛出一个 setter(如SetRow()
要么忽略无效值,要么在给定无效值时抛出异常(。 如果这由Dimensions
类型一致地完成,那么Matrix<T>
可以安全地假设维度是有效的 - 因为不可能传递具有无效值的Dimensions
实例。 这意味着,Matrix<T>
不需要检查。
- 我应该使用什么来代替void作为变体中的替代类型之一
- boost::asio::steady_timer()与sleep()我应该使用哪一个
- 我应该实现右值推送功能吗?我应该使用std::move吗
- 我是C++编程的新手,这些代码之间有什么区别,我应该使用哪一个
- 我应该删除矢量<short>吗?
- 我应该如何修改此代码以使用给定字符串中的字母打印菱形图案
- 我应该在锁定TBitmap画布后解锁它吗
- 为什么我应该在异常处理中使用std::cerr而不是std::cout
- 我应该避免多重实现继承吗
- 为了方便起见,我应该避免公开私有字段变量吗
- 我收到同义重复编译器错误。我应该如何修复"类型"X"的参数与类型"X"的参数不兼容?
- 违反const正确性:我应该现实地期待什么问题
- 我应该如何表示我拥有的连续元素序列?
- 我应该将除 .cpp 以外的其他文件添加到 git 中吗?
- 我应该如何从 stdin C++ 中读取可变长度的格式字符串?
- 我有一个对象,它将在整个程序的持续时间内实例化,但一个类成员不会,我应该动态分配它吗?
- 我应该如何捕捉out_of_range异常?
- C++ 返回异常,我应该释放资源吗?
- 如果我将内存动态分配给静态变量,我应该释放它还是会自动释放它
- 我应该释放内部分配的MFT输出缓冲区的返回IMFSample吗