C++使用 auto_ptr 引用作为输出变量是否惯用?

发布于 2024-11-24 15:39:37 字数 560 浏览 11 评论 0 原文

假设我想编写工厂方法,该方法应该在堆上分配异构对象并将它们返回给调用者。我正在考虑这样设计 API:

bool MakeEm(auto_ptr<Foo>& outFoo, auto_ptr<Bar>& outBar) {
  ...
  if (...) {
    return false;
  }
  outFoo.reset(new Foo(...));
  outBar.reset(new Bar(...));
  return true;
}

这允许调用者执行此操作:

auto_ptr<Foo> foo;
auto_ptr<Bar> bar;
MakeEm(foo, bar);

我的问题是:“这是惯用的吗?如果不是,正确的方法是什么?”

我能想到的替代方法包括返回 auto_ptrstruct,或者编写工厂 API 来获取原始指针引用。它们都需要编写更多代码,而后者在异常安全方面还有其他问题。

Suppose I want to write factory method that is supposed to allocate heterogeneous objects on the heap and return them to the caller. I am thinking of designing the API like this:

bool MakeEm(auto_ptr<Foo>& outFoo, auto_ptr<Bar>& outBar) {
  ...
  if (...) {
    return false;
  }
  outFoo.reset(new Foo(...));
  outBar.reset(new Bar(...));
  return true;
}

This allows a caller to do this:

auto_ptr<Foo> foo;
auto_ptr<Bar> bar;
MakeEm(foo, bar);

My question is: "Is this idiomatic? If not, what is the right way to do this?"

The alternative approaches I can think of include returning a struct of auto_ptrs, or writing the factory API to take raw pointer references. They both require writing more code, and the latter has other gotchyas when it comes to exception safety.

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

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

发布评论

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

评论(5

尹雨沫 2024-12-01 15:39:37

询问某事是惯用的,会给你一些非常主观的答案。
然而,总的来说,我认为 auto_ptr 是传达所有权的好方法,因此作为类工厂的返回 - 这可能是一件好事。
我想重构这一点,这样

  1. 你就可以返回一个对象而不是 2 个。如果你需要 2 个紧密耦合的对象,那么如果没有彼此它们就无法存在,我想说你有充分的理由使用 is-a 或 has-a重构。
  2. 这是C++。真正问问自己是否应该返回一个表示成功的值,迫使工厂的消费者每次都必须检查。从工厂中类的构造函数抛出异常或传递异常。您是否愿意接受 false 并尝试对未初始化的 auto_ptr 进行操作?

Asking of something is idiomatic can get you some very subjective answers.
In general, however, I think auto_ptr is a great way to convey ownership, so as a return from a class factory - it's probably a Good Thing.
I would want to refactor this, such that

  1. You return one object instead of 2. If you need 2 objects that are so tightly coupled they cannot exist without each other I'd say you have a strong case for is-a or has-a refactoring.
  2. This is C++. Really ask yourself if you should return a value indicating success, forcing the consumer of your factory to have to check every time. Throw exceptions or pass exceptions from the constructors of your classes in the factory. Would you ever want to be OK with false and try to operate on uninitialized auto_ptr's?
软糖 2024-12-01 15:39:37

您不必构建自己的结构来返回两个值 - 您可以使用 std::pair。在这种情况下,返回两个值并没有太多语法开销。这个解决方案确实存在一个问题,即“.first”和“.second”不是非常具有描述性的名称,但如果涉及的类型和函数的名称使意图足够清晰,那么这不一定是问题。

如果您使用的是 C++0x,则可以使用 unique_ptr 代替 auto_ptr,并且调用者可以使用 auto 而不必键入较长的 std::pair、std::unique_ptr> 。 。如果您不使用 C++0x,您可以考虑使用 typedef。

如果您返回这两个值,那么您将没有空间容纳该布尔值。您可以使用 C++0x 元组返回所有三个值。您还可以通过引发异常或返回空指针来指示错误。我更喜欢一个例外,假设错误是罕见/异常的。

正如其他答案所指出的,通常最好有两个单独的函数,每个函数返回一个对象。如果您不能这样做,因为两个对象的初始化是紧密相连的,那么您可以创建一个封装初始化的类。您可以将必要的信息传递给构造函数以生成两个对象(需要异常来发出错误信号),然后在该类上使用两个方法,每个方法生成一个对象。

You don't have to make up your own struct to return two values - you can use std::pair. In that case there isn't much syntactic overhead in returning the two values. This solution does have the problem that ".first" and ".second" aren't very descriptive names, but if the types involved and the name of the function make the intent clear enough then that's not necessarily a problem.

If you are using C++0x you could use unique_ptr insted of auto_ptr and the caller can use auto instead of having to type the longer std::pair<std::unique_ptr<A>, std::unique_ptr<B>>. If you are not using C++0x you might consider using a typedef for that instead.

If you return the two values then you won't have space for the bool. You could use a C++0x tuple to return all three values. You could also indicate error by throwing an exception or by returning null pointers. I would prefer an exception assuming that the error is rare/exceptional.

As other answers have pointed out, it is often preferable to have two separate functions that each return a single object. If you can't do that because the initialization of the two objects is inextricably linked then you could make a class that encapsulates the initialization. You could pass the necessary information to make the two objects to the constructor (requires exception to signal errors) and then have two methods on that class that yield one object each.

情绪 2024-12-01 15:39:37

我们假设返回值 false 表示“不查看输出参数”。

然后我要做的就是去掉 bool 返回值,返回一个具有所需 auto_pointers 的结构或对,并在错误条件下抛出。

Let's assume that a return value of false means "don't look at the output parameters".

Then what I would do is get rid of the bool return value, return a struct or pair that has the auto_pointers you want, and throw in the error condition.

云仙小弟 2024-12-01 15:39:37

通常,当您有 auto_ptr 参数时,它们不是引用。

这是因为当您将某些内容传递给采用 auto_ptr 的函数时,您希望该函数获得所有权。如果您通过引用传递,它实际上并不获取该对象(它可能会获取该对象)。

这是一个微妙的点,但最终您需要看看您的界面试图向用户传达什么信息。

此外,您似乎将其用作 out 参数。
就我个人而言,我从未见过这个用例(但我可以看到它),只是记录您想要做什么,更重要的是为什么

Usually when you have auto_ptr parameters they are not references.

This is because when you pass something to a function that takes auto_ptr you are expecting that function to take ownership. If you are passing by reference it does not actually take the object (it may take the object).

Its a subtle point, but in the end you need to look at what your interface is trying to say to the user.

Also you seem to be using it as an out parameter.
Personally I have never seen this use case (but I can see it) just document what you are trying to do and more importantly why.

别再吹冷风 2024-12-01 15:39:37

作为一般规则,如果它涉及 auto_ptr,则它不是惯用的。一般来说,该结构并不是很惯用——通常,您将为每个函数创建一个函数,按值返回并在失败时抛出异常,如果您需要共享变量,请将其设为对象。

As a general rule, if it involves auto_ptr, it's not idiomatic. In general, the structure is not idiomatic too- normally, you'd make one function for each, return by value and throw an exception if they fail, and if you need to share variables, make it an object.

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