处理无法以预定方式创建的对象,C++
假设我有一个类A,它使用动态内存分配,如数组或矩阵。在创建对象A的过程中,通过构造函数传递参数来确定分配多少内存空间。处理无法以预定方式创建的对象,C++
class A
{
int * ptr;
int size;
void allocate() noexcept;
void destroy() noexcept;
public:
A(int) noexcept;
~A() noexept;
}
void A::destroy() noexcept
{
if(ptr!=nullptr)
delete [] ptr;
}
A::~A() noexcept
{ destroy();}
void A::allocate() try
{
ptr = new int[n];
}
catch (std::bad_alloc & ex)
{
std::cerr << ex.what();
destroy();
}
A::A(int n) noexcept : size(n) { allocate(); };
这些东西是一种很好的做法,设计明智吗?对于无法以预定方式创建的对象会发生什么情况?它会像“僵尸”一样“活着”吗?还是会被摧毁?
在矩阵方案中该怎么办,矩阵分配多个新的陈述?
智能指针,STL和那种东西不是这里的一个选项。
读我:这个班是纯粹为此类问题而设的示范班。它并不遵循0/3/5的规则,因为编写代码太多只是针对一个问题,对于这个问题并不重要。关于这些问题已经存在一堆问题。
问:这些东西是一种很好的做法,设计明智吗?
A.这样做本身并没有什么坏处,它取决于要求。一般来说,如果你想确保构造函数不会抛出(这可能是你的意图),这是很好的,并且如果你分配的数据对于对象的操作不是关键的,那么它就是有意义的。在大多数情况下,如果构造函数中出现故障,最好抛出一个异常。请注意,如果你使用这个,你在访问ptr []时也需要检查NULL是否为NULL。
问:无法按照预期方式创建的对象会发生什么情况? 它会像“僵尸”一样“活着”吗?还是会被摧毁?
答:这可以通过两种方式发生: 1.未能为对象A本身分配内存。在这种情况下,它将取决于用于分配内存的方法。如果它的“新”,那么它会默认抛出一个异常。 2.未能在分配中为整数数组分配内存。在这种情况下,你会发现异常。在catch块中,在这种情况下,使用destroy()重新分配ptr是不必要的,因为try块将失败的唯一方式是不能为n个整数数组分配内存。 A的构造函数会隐藏这个失败,为对象A分配的内存将保持原样。
问:在矩阵方案中,矩阵分配多个新语句时该做什么?
答:你的意思是如果你在for循环/多个新语句中为ptr分配内存会发生什么?如果是这样,除非在这种情况下,已分配给ptr []的任何内存将保持原样并且您需要catch块中的destroy()调用以取消分配分配给ptr []的所有内存,否则行为将会相同。注意在销毁你将再次需要分别检查NULL和释放每个数组元素。
不,这些东西是一个坏主意。
根本问题是可组合性。像每个OO语言一样,C++允许用户定义的类型。这些类型可以包含不同类型的成员。 C++定义了如何创建和销毁这些组合类型的规则。
C++规则是在写出例外的情况下编写的。他们是而不是写在僵尸对象的脑海。创建成员时的例外会被传播,并且其兄弟会被正确销毁。成员的僵尸状态是而不是繁殖,并且兄弟姐妹很难清理(如果有的话)。
现在你可能会认为,不是依赖C++规则,而是可以引入一个公司方面的编码标准,即复合对象应该有一个检查所有成员的方法bool isZombie() const
。但是C++有模板容器。 std::vector<YourClass>
确实不是有一个isZombie()
方法; std::vector<>
不符合贵公司的编码标准。但是,std::vector<T>
确实从T::T()
宣传例外。当它发生时,它不会破坏内部状态。甚至没有通过vector.resize()
的一半。
为什么不让应该扔掉的东西扔掉? – juanchopanza
为什么在失败的分配中调用'destroy'?未能分配意味着你没有任何东西来“删除”。 –
“这是一个很好的解决方案吗?” - 什么问题? –