我有一个类似的类vector
,主要是动态大小的数组。我正在为资源有限的平台编写它,因此我必须不要使用异常。
显然,使用运算符重载来简化此类的接口,必须在某些运算符重载函数中执行动态分配。赋值运算符(=)是一个示例。
但是,没有例外,以合理的方式通知调用者错误的分配错误,同时仍然要恢复强大的错误安全性,这是相当具有挑战性的。我可能具有该类的error属性,在每次涉及动态分配的调用之后,调用方都必须检查该类的错误属性,但这似乎不是一个最佳解决方案。
编辑:
这是我目前所拥有的最好的主意(在上段中以不太理想的解决方案突出显示),任何改进将不胜感激:
dyn_arr & dyn_arr::operator=(dyn_arr const & rhs) {
if (reallocate(rhs.length)) // this does not destroy data on bad alloc
error |= bad_alloc; // set flag indicating the allocate has failed
else {
size_t i;
for (i = 0; i < rhs.length; ++i) // coppy the array
arr[i] = rhs.arr[i]; // assume this wont throw an exceptions and it wont fail
}
return *this;
}
然后致电:
dyn_arr a = b;
if (a.error)
// handle it...
我没有编写此文件,因此可能会有错别字,但希望您能理解。
这里有两个单独的问题。
第一个与操作员重载有关。正如CashCow所提到的,C ++中的重载运算符只是函数调用的语法糖。特别是,运营商并不需要return *this
。这仅仅是为了方便操作员链接而创建的编程约定。
现在,链接赋值运算符(a = b = c = ...
)在C ++应用程序中是一个极端情况。因此,最好通过明确禁止dyn_arr
类的用户使用链式分配运算符来使自己更好。这样您就可以自由地从操作员那里返回错误代码,就像从常规函数中返回一样:
error_t operator = (dyn_arr const & rhs) {
void *mem = realloc(...);
if (mem == NULL) {
return ERR_BAD_ALLOC; // memory allocation failed
}
...
return ERR_SUCCESS; // all ok
}
然后在调用者代码中:
dyn_arr a, b;
if ((a = b) != ERR_SUCCESS) {
// handle error
}
第二个问题与您提供的实际示例有关:
dyn_arr a = b;
此示例不会调用重载的分配运算符!相反,它的意思是“构建dyn_arr
对象a
以b
作为参数传递给构造”。因此,此行实际上调用的副本构造函数dyn_arr
。如果您想了解原因,请考虑效率。如果该行的语义包括调用赋值运算符,运行时系统将不得不做两件事情,因为这行的结果:构建a
了一些默认状态,然后立即将其分配给摧毁国家a
的状态b
。相反,只需做一件事-调用副本构造即可。(并导致相同的语义,假定复制构造函数和赋值运算符的任何合理实现。)
不幸的是,您正确地认识到这个问题很难解决。除了抛出异常之外,似乎没有一种真正优雅的方法来处理构造函数中的故障。如果您不能这样做,请执行以下任一操作:
有关更多详细信息,请参见如何在C ++中处理构造函数中的失败?
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句