我对 RAII 的了解越多,我就越明白使用堆栈是确保代码异常安全的方法。
这是否意味着每次我new()
在我的代码中做某事时,我都做错了什么,因为有更好的方法可以使用 RAII 原则来做到这一点?
我认为您还没有完全理解 RAII 的真正含义。动态分配,就像程序中需要文件、数据库连接等其他资源一样。RAII 专注于如何管理这些资源,而要走的路是让具有自动存储持续时间的对象(堆栈或作为另一个对象的成员)管理资源。
这并不意味着每个资源都必须在堆栈中分配,而是如果您在堆中分配某些东西,您应该将管理该内存的责任委托给堆栈中的对象。
如果你使用 ,你不一定做错了什么new
,但值得检查你做对了。
new
应立即置于智能指针的控制之下,通常是直接将其传递给构造函数。shared_ptr
,那么你可能做错了。您可能应该make_shared
改用。在某些情况下您不应该(使用weak_ptr
大对象),而在某些情况下您不应该(没有 Boost 的 C++03)。delete
,那么您几乎做错了,除非您正在编写自己的智能指针类。即使这样,您的智能指针也可能能够使用另一个智能指针来节省工作。new
仅因为对象“对于堆栈而言太大”而使用,请考虑编写一个充当对象句柄的类,使用unique_ptr
或scoped_ptr
管理它,以便从用户的角度来看他们处理的对象是自动变量。如果您愿意,可以将其扩展到完整的 PImpl 成语。即使您不想要另一个类,也请考虑一个创建对象并将 a 返回unique_ptr
给它的函数,然后您可以调用 like auto foohandle = give_me_a_foo();
。然后give_me_a_foo
contains new
,但其他用户代码没有,并且您鼓励将内容自动填充到 RAII 对象中的做法。在 C++ 中,有替代 RAII 的资源管理策略,但如果你使用它们,你就会知道,这会影响什么是“错误的”。
一点也不。如果野兽的本质(分配要求)是真正动态的,那么最终它要么来自堆,要么来自堆栈指针。
您能做的最好的事情就是为您使用范围保护的包装。(当我需要一个受范围保护的动态临时缓冲区时,我不能告诉你我使用 std::vector<> 的频率)。这是使用维护良好和设计良好的库(如 STL 等)的最理想原因之一。与 C# 或 Java 不同,它是可预测的,在真正需要时具有巨大的价值。
不,堆栈空间非常有限,所以你不想在上面放很多东西,因此术语堆栈溢出。此外,如果您需要一个对象的生命周期比您的函数长,那么您不能将其放入堆栈。