处理无法以预定方式创建的对象,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的规则,因为编写代码太多只是针对一个问题,对于这个问题并不重要。关于这些问题已经存在一堆问题。

+1

为什么不让应该扔掉的东西扔掉? – juanchopanza

+1

为什么在失败的分配中调用'destroy'?未能分配意味着你没有任何东西来“删除”。 –

+1

“这是一个很好的解决方案吗?” - 什么问题? –

问:这些东西是一种很好的做法,设计明智吗?

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()的一半。