Objective C“自动释放”在 C++ -- 控制对象生命周期的标准方法?

发布于 2024-12-17 16:15:31 字数 758 浏览 1 评论 0原文

我正在将一些代码从 Objective C 移植到 C++。我不像对 Objective C 那样熟悉 C++ 设计模式。在 Cocoa 世界中,有一种非常常见的模式,即编写返回“自动释放”对象的工厂方法。事情很简单,例如:

- (MyClass *)load {

    MyClass* obj = [[MyClass alloc] init];
    return [obj autorelease];
}

这很简单且易于理解。该方法拥有它分配的内存,但可以将其交还给调用者,同时放弃所有权。它不必知道或关心调用者如何处理该内存。如果它保留它,该对象就会生存。如果完全忽略它,则在当前调用堆栈展开后的某个时间将释放内存。

我在 C++ 中带着一些恐惧来处理这个问题,因为它的非引用计数环境似乎没有像 autorelease 这样干净的东西,或者任何类型的所有权策略都定义得很好Cocoa 框架中的那些。 C++ 中这种模式的最佳实践是什么?

我知道 auto_ptr,但对其使用也有很多担忧,而且它似乎有太多缺点,无法像 autorelease 那样普遍存在(奇怪的复制语义、不支持数组、不兼容)使用 STL 容器等)。

Boost 智能指针也是一个明显的候选者,有些甚至实现了自己的引用计数。对于我来说,必须依靠第三方库来完成如此平凡的事情似乎有点奇怪。

另一个带有 C 味道的选项是不释放返回的内存,而是通过普遍采用的命名约定来指示调用者现在拥有返回的对象。这看起来有点过时,并且如果调用者不小心忽略返回值,很容易出现隐形泄漏。

I'm in the process of porting some code from Objective C to C++. I'm not as familiar with C++ design patterns as I am with Objective C. In the Cocoa world, there is the very common pattern of writing a factory method that returns an "autoreleased" object. Somethings as simple as:

- (MyClass *)load {

    MyClass* obj = [[MyClass alloc] init];
    return [obj autorelease];
}

This is simple and easy to understand. The method owns the memory it allocates, but can hand it back to the caller, while simultaneously relinquishing ownership. It doesn't have to know or care what the caller does with that memory. If it retains it, the object will survive. If it is completely ignored, the memory will be freed sometime after the current call stack is unwound.

I'm approaching this with some trepidation in C++, because its non ref-counted environment doesn't seem to have anything quite as clean as autorelease, or any kind of ownership policy that is as well defined as those in the Cocoa frameworks. What are the best practices for this kind of pattern in C++?

I'm aware of auto_ptr, but there are also multitudes of concerns with its use, and it seems to have too many shortcomings to be as ubiquitous as autorelease (weird copy semantics, no support for arrays, incompatibility with STL containers, etc).

Boost smart pointers are also an obvious candidate, and some even implement their own reference counting. It seems a little strange to me to have to lean on a 3rd party library for something this mundane though.

Another option that reeks of C would be to just not release the returned memory, but indicate via come commonly adopted naming convention that the caller now owns the returned object. This seems a bit archaic, and is prone to invisible leaks should the caller accidentally ignore the return value.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

握住你手 2024-12-24 16:15:31

C++03 世界(即 C++11 之前的版本)中的“最佳实践”是以下两件事之一:

  1. 什么也不做。这本质上是假设/约定的内存所有权。如果函数返回一个指针,您应该知道谁拥有它。通常,文档会告诉你。内存所有权或转让所有权没有特定的语法。

    不幸的是,这就是大量 C++ 代码管理内存的方式。只要每个人都知道他们应该做什么以及谁负责什么,它就可以发挥作用。

  2. 使用某种形式的智能指针。 std::auto_ptr 很奇怪,但这与 C++03 中的轻量级差不多。不,您不能将它们放在标准容器中,但它确实定义了特定的所有权模式。 boost::shared_ptr 是一种更有效的方法,并且在许多其他地方更有用。

C++11 提供了 std::unique_ptr,它本质上是一个“固定”auto_ptr。它依赖于C++11语言特性(对象移动),所以你不能只用C++03编写一个。您可以将它们存储在标准容器等中。但你不能只是传递它们。顾名思义,它们是唯一的:只有其中一个可以指向该对象。当 unique_ptr 被销毁时,它会删除它引用的对象。

您只能通过放弃来转让 unique_ptr 的所有权。也就是说,您不能共享所有权。您可以返回所有权,这意味着调用者现在拥有它。您可以将所有权传递给另一个函数,这意味着该函数拥有它。但没有两个实体可以通过 unique_ptr 拥有一个对象。

unique_ptr 将是处理此类函数的首选方法。如果用户想要自己存储它,那么他们可以将其释放到 std::shared_ptr 中(这也被 C++11 采用)。

The "best practices" in the C++03 world (that is, pre-C++11) are one of two things:

  1. Do nothing. This is essentially memory ownership by assumption/convention. If a function returns a pointer, you should know who owns it. Usually, the documentation will tell you. There is no specific syntax for ownership of memory or of transferring ownership.

    This is how an unfortunately large amount of C++ code out there manages memory. It can work, so long as everyone knows what they should be doing and who is responsible for what.

  2. Use some form of smart pointer. std::auto_ptr is odd, but that's about as lightweight as it gets in C++03. No, you can't stick them in standard containers, but it does define a specific pattern of ownership. A boost::shared_ptr is a more effective one, and is more useful in many other places.

C++11 offers std::unique_ptr, which is essentially a "fixed" auto_ptr. It relies on C++11 language features (object movement), so you can't just write one in C++03. You can store them in standard containers and everything. But you can't just pass them around. As the name suggests, they're unique: only one of them can exist which points to that object. When that unique_ptr is destroyed, it deletes the object it references.

You can transfer ownership of a unique_ptr only by giving it away. That is, you cannot share ownership. You can return ownership, which means that the caller now owns it. You can pass ownership to another function, which means that that function owns it. But no two entities can own an object through a unique_ptr.

unique_ptr would be the preferred method of handling a function like this. If the user wants to store it non-uniquely themselves, then they can release it into a std::shared_ptr (which was also adopted into C++11).

巷子口的你 2024-12-24 16:15:31

我会查看 boost 中的 shared_ptr

C++ 世界就是关于库的。因为没有人拥有 C++(与 Objective-C 不同),所以它随着社区的需求而增长。

I would look at the shared_ptr in boost.

The C++ world is all about libraries. Because no one owns C++ (unlike Objective-C), it grows as the community sees the need.

羅雙樹 2024-12-24 16:15:31

嗯,最像 C++ 的选项是使用智能指针。

根据我的阅读,引用计数指针是最好的选择,在 C++11 标准中,您可以使用 shared_ptr

Well the most c++-like option is using smart pointers..

From what I read, reference counting pointers are your best bet, in the c++11 standard you can use the shared_ptr

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文