本文介绍了目标C“自动释放”在C ++ - 标准的方式来控制对象的生命周期?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在将一些代码从Objective C移植到C ++。我不熟悉C ++设计模式,因为我使用Objective C.在Cocoa世界,有一个非常常见的模式,写一个工厂方法返回一个自动释放对象。一些简单的例子:

   - (MyClass *)load {

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

这很简单,容易理解。该方法拥有它分配的内存,但可以将其传回给调用者,同时放弃所有权。它不必知道或关心呼叫者对该记忆的作用。如果它保留,对象将继续存在。如果它被完全忽略,内存将在当前调用堆栈解开后的某个时间释放。



我在C ++中使用一些trepidation,计数的环境似乎没有像 autorelease 那样清晰,或者任何类型的所有权策略,像Cocoa框架中那样定义。 C ++中这种模式的最佳实践是什么?



我知道auto_ptr,但也有许多关注它的使用,有太多的缺点,像 autorelease (奇怪的复制语义,不支持数组,与STL容器不兼容等)无处不在。



Boost智能指针也是一个显而易见的选择,有些甚至实现自己的引用计数。对我来说,似乎有点奇怪,为了这个世俗的东西,不得不靠在第三方的图书馆。



另一个选择C的方法是只是不是释放返回的内存,而是通过常用的命名约定表示调用者现在拥有返回的对象。

解决方案

最佳实践是一个很好的例子, 在C ++ 03世界(即,pre-C ++ 11)是两件事之一:


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



    这是一个不幸的是大量的C ++代码管理内存。它可以工作,只要大家都知道他们应该做什么,谁负责什么。


  2. 使用某种形式的智能指针。 std :: auto_ptr 是奇怪的,但是它是那么轻量级,因为它在C ++ 03。不,你不能把它们粘在标准容器中,但它确实定义了一种特定的所有权模式。 boost :: shared_ptr 是一种更有效的方法,在许多其他地方更有用。


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



您可以 > unique_ptr 的所有权只有通过给予它。也就是说,您无法 分享所有权。您可以返回所有权,这意味着呼叫者现在拥有它。您可以将所有权传递给另一个函数,这意味着该函数拥有它。但是没有两个实体可以通过 unique_ptr 拥有对象。



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


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.

解决方案

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).

这篇关于目标C“自动释放”在C ++ - 标准的方式来控制对象的生命周期?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-27 10:10