0

对 RAII 的了解越多,我就越明白使用堆栈是确保代码异常安全的方法。

这是否意味着每次我new()在我的代码中做某事时,我都做错了什么,因为有更好的方法可以使用 RAII 原则来做到这一点?

4

4 回答 4

2

我认为您还没有完全理解 RAII 的真正含义。动态分配,就像程序中需要文件、数据库连接等其他资源一样。RAII 专注于如何管理这些资源,而要走的路是让具有自动存储持续时间的对象(堆栈或作为另一个对象的成员)管理资源。

这并不意味着每个资源都必须在堆栈中分配,而是如果您在堆中分配某些东西,您应该将管理该内存的责任委托给堆栈中的对象。

于 2012-09-15T02:19:32.000 回答
2

如果你使用 ,你不一定做错了什么new,但值得检查你做对了。

  • 表达式的结果new应立即置于智能指针的控制之下,通常是直接将其传递给构造函数。
  • 如果那个智能指针是 a shared_ptr,那么你可能做错了。您可能应该make_shared改用。在某些情况下您不应该(使用weak_ptr大对象),而在某些情况下您不应该(没有 Boost 的 C++03)。
  • 如果您使用delete,那么您几乎做错了,除非您正在编写自己的智能指针类。即使这样,您的智能指针也可能能够使用另一个智能指针来节省工作。
  • 这不是必需的,但是如果您new仅因为对象“对于堆栈而言太大”而使用,请考虑编写一个充当对象句柄的类,使用unique_ptrscoped_ptr管理它,以便从用户的角度来看他们处理的对象是自动变量。如果您愿意,可以将其扩展到完整的 PImpl 成语。即使您不想要另一个类,也请考虑一个创建对象并将 a 返回unique_ptr给它的函数,然后您可以调用 like auto foohandle = give_me_a_foo();。然后give_me_a_foocontains new,但其他用户代码没有,并且您鼓励将内容自动填充到 RAII 对象中的做法。

在 C++ 中,有替代 RAII 的资源管理策略,但如果你使用它们,你就会知道,这会影响什么是“错误的”。

于 2012-09-15T08:45:24.323 回答
1

一点也不。如果野兽的本质(分配要求)是真正动态的,那么最终它要么来自堆,要么来自堆栈指针。

您能做的最好的事情就是为您使用范围保护的包装。(当我需要一个受范围保护的动态临时缓冲区时,我不能告诉你我使用 std::vector<> 的频率)。这是使用维护良好和设计良好的库(如 STL 等)的最理想原因之一。与 C# 或 Java 不同,它是可预测的,在真正需要时具有巨大的价值。

于 2012-09-15T01:15:41.133 回答
0

不,堆栈空间非常有限,所以你不想在上面放很多东西,因此术语堆栈溢出。此外,如果您需要一个对象的生命周期比您的函数长,那么您不能将其放入堆栈。

于 2012-09-15T01:12:24.337 回答