避免使用 "throwing" 构造函数进行堆分配
Avoiding heap allocation with "throwing" constructors
假设我有一些类Foo
没有定义默认构造函数,throws
在非默认构造函数中。在初始化该类型的新对象时,我希望捕获任何异常并返回,否则继续使用该对象。我注意到,如果可能的话,很难在堆栈或通过使用共享指针来初始化这个对象,因为我试图避免管理内存。
失败1
Foo f; // doesn't work, no default constructor
try { f = Foo(...); }
失败2
try {
Foo f(...)
}
catch(...) {}
// doesn't work, f is inaccessible
失败3
boost::shared_ptr<Foo> pf;
try { pf = new Foo(...); } // no assignment operator
我必须…
Foo *f;
try { f = new Foo(...) } // okay, let's just manage the memory
有办法吗?
编辑
好的,这是可行的,尽管不是最干净的。有没有更"标准"的方式?
boost::shared_ptr<Foo> pf;
try { pf = boost::shared_ptr<Foo>(new Foo(...)); }
智能指针有一个reset
方法:
boost::shared_ptr<Foo> f;
//...
f.reset(new Foo(...));
这解决了你的"失败#3",让你可以做你想做的事情。
保持f
堆栈为基础的正确方法是尊重范围:
try {
Foo f(...);
... entire code using f ...
}
catch(...) {}
一个解决方案是使用boost::optional
(或c++ 14的std::optional
):
boost::optional<Foo> f;
try { f = Foo(...); }
如果您使用正确的.reset()方法,您的智能指针情况和喜欢工作很好。
然而,这个问题不适合正常的用例,要么是类设计不当,要么是您使用不当。正常使用应该像case#1一样,将F放在块内。或者不尝试阻塞并将catch留给上游。
编辑:针对最近的评论和原始问题,我坚持自己的立场,即在最终用户代码中使用try块是不受欢迎的。对于使用特定抛出策略处理第三方组件的情况,如果不符合我的需要,我会编写包装器,将异常转换为错误返回或错误代码抛出异常。并使用扩展组件
在这种情况下,用户被抛出tor所困扰。因此,它可以通过在函数中包装该actor来处理:
Foo* new_foo( ARGS )
{
try{
return new Foo( ARGS );
}
catch( const FooException& )
{
return NULL;
}
}
然后让客户端代码没有try块,更重要的是,没有赋值。只要const unique_ptr<Foo> p(new_foo(...))
就行了。
相关文章:
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- 具有自定义构造函数 (C++) 的类型的动态数组分配
- C 字符串在显式构造函数中分配值C++?
- 如何为 std::vector 分配内存,然后稍后为某些元素调用构造函数?
- 在构造函数中分配内存失败是如何冒泡的
- 当我尝试通过构造函数分配 char 数组时出现错误
- 如何使用函数(而不是构造函数)将派生类对象分配给基类指针
- 动态分配的内存构造函数
- 在 c++ 的构造函数中分配对象向量时出错
- 如何在构造函数中构造对象并分配引用
- 在C++中,从构造函数中将字符串文本分配给成员const char*变量时会发生什么
- 如何在构造函数中访问类变量以分配它们,而无需在C++中使用此指针
- 如何捕获源自静态分配对象的构造函数的异常?
- QThreads - 为什么要在构造函数中分配内存而不是使用普通的类成员?
- 使用 "new" 命令在 C++ 中的类构造函数中分配 2D 数组
- 在C++中,当重新分配对象时,为什么构造函数在析构函数之前触发?
- 如何使用每个对象的单个构造函数参数动态分配C++对象数组?
- 将动态分配对象传递到 boost::any 构造函数中
- 我们是否应该从派生类调用基类移动复制/分配构造函数
- 为什么C3分配构造函数从未使用过