避免在构造函数中分配或保持简单性(和 RAII?
Avoid allocating in constructor or preserve simplicity (and RAII?)
我已经把一个游戏引擎作为一个项目来学习更多关于 c++ 大约 8 个月了。我已经到了这样一个阶段,为了避免分配构造函数(在大学讲师的建议下(,我为所有对象提供了虚拟 setup(( 方法,以及一个布尔值来标记设置方法是否已被调用。但是,我遇到了各种逻辑错误,由于在设置中进行了分配,因此无法在构造函数中执行任何操作是一个巨大的痛苦。我也一直在阅读有关 RAII 的信息,似乎最好只在构造函数中分配,这样我就不必调用设置方法。
通过构造函数中的 new 分配内存有多糟糕?我应该这样做以符合 RAII 吗?
编辑 - 只是为了澄清,人们正在使用std::vector容器等指出。我说的是为更多对象分配内存,而不是为数组和事物分配内存。例如 - 按钮对象需要为自己创建一个转换组件、一个动画组件和一个渲染组件。目前,在 setup(( 中,我将使用 new 创建它们。使用智能指针等是否意味着我不需要新关键字?
我正在创建的对象被转发到一个名为addComponent(组件*(的基类方法,该方法将此组件存储在组件* s的std::vector中,因此我无法在方法/构造函数的末尾清理这些对象。
我的印象是
ButtonClass()
{
SomeComponent * sc = new SomeComponent ();
addComponent(sc);
}
工作正常,但是
ButtonClass()
{
SomeComponent sc = SomeComponent ();
addComponent(&sc);
}
将导致 sc 被清理,并且传递给 addComponent 的对它的引用将是指向空内存的指针。
如果使用智能指针否定了这一点,那么我误解了他们,我认为他们只是以比调用new然后删除更整洁的方式为我删除了东西。
我得到"从不分配构造函数"的原因是,如果构造函数失败,则无法恢复该内存。但是同意下面的评论,我一直怀疑如果发生这种情况,我无论如何都会终止......
一个好的经验法则是每个类都应该有一个责任。我们已经有一些(模板(类负责处理堆分配的内存,例如std::vector
、std::string
和std::unique_ptr
。大多数情况下,您应该使用这些来避免给类额外的内存处理责任。
现在,您可能需要标准类未提供的特定类型的内存处理。或者更常见的是,您有一些其他非内存资源也需要清理处理 - 例如临时文件。在这些情况下,"一个阶级,一个责任"的原则仍然适用。将每个此类资源包装在其自己的资源管理类中。需要三个资源的更复杂的对象只有三个成员,每个成员处理一个资源。
C++现在确保即使出现异常,资源也不会丢失。即使在某个复杂对象的构造函数中间无法创建一个成员,C++也会安排到目前为止创建的所有成员都被销毁,并且只销毁这些成员。这为您提供了一种全有或全无的方法。没有半途而废的对象。
需要特别明确的是:这仅适用于构造函数。它不适用于您自己的setup()
。换句话说,C++有特定的规则来使资源获取在构造函数中工作,并且只在那里工作。这就是为什么术语是"资源获取是初始化"或RAII。您的讲师从根本上不理解C++如果他们建议不要在构造函数中分配资源。
如果你有很多构造函数做几乎同样的事情,这种 init(( 或 setup(( 方式是很好的。
但我认为,这本身就是一个设计错误。
所以,我建议再次阅读你的讲师建议,如果它对你来说仍然意味着同样,那么阅读其他人的意见,比如斯科特迈耶斯。
构造函数是分配资源的自然位置。我见过读取完整数据库以设置应用程序的构造函数。
使用智能指针来分配东西,然后你就免除了关注它们的职责,因为它们足够聪明,可以照顾好自己。
玩得开心!
- 具有瞬态资源的RAII类
- 在c++中用vector填充一个简单的动态数组
- (C++)分析树以计算返回错误值的简单算术表达式
- 我的简单if-else语句是如何无法访问的代码
- 使用简单类型列表实现的指数编译时间.为什么
- 如何在BST的这个简单递归实现中消除警告
- 一种在C++中读取TXT配置文件的简单方法
- 关于简单C++函数(is_palindrome)的逻辑的问题
- 显示错误输出的简单数组排序程序
- 当无法使用模板和宏时,生成类型变体C++代码的最简单方法是什么?
- 退出简单while循环时出现问题
- 为什么简单的算术减法在"if"条件下不起作用?
- 使用RAII在给定次数的迭代后重新分配资源
- C++-字符串是否包含一个带有简单循环的单词
- 关于 c++ 函数中指针赋值的简单问题
- 从函数返回任意简单类型的数据
- 如何在没有函数的情况下编写此代码并使C++更简单?
- 这个简单的例子被认为是raii
- c ++新的C数组分配,RAII或简单的shared_ptr/boost::shared_array
- 在GCC和Clang下,带有lambda的简单RAII包装器的复制初始化意外失败