5

考虑一下我最近在我们的代码库中看到的以下示例代码:

void ClassA::ExportAnimation(auto_ptr<CAnimation> animation)
{
... does something
}

// calling method:
void classB::someMethod()
{
  auto_ptr<CAnimation> animation (new CAnimation(1,2));
  ClassA classAInstance;
  classAInstance.ExportAnimation(animation)
  ... do some more stuff
}

我不喜欢这样 - 宁愿这样写:

void ClassA::ExportAnimation(CAnimation* animation)
{
    ... does something
}

// calling method:
void classB::someMethod()
{
  auto_ptr<CAnimation> animation (new CAnimation(1,2));
  ClassA classAInstance;
  classAInstance.ExportAnimation(animation.get())
  ... do some more stuff
}

但这真的有问题吗?

4

4 回答 4

4

auto_ptr 明确地声明指针的所有权被传递。普通指针不是自记录的。

于 2010-08-09T12:01:20.137 回答
4

这一切都取决于ExportAnimation它是什么以及如何实施。

它是否仅在通话期间使用该对象然后离开它?

然后转换为引用并传递一个真实的引用。不需要传递成员资格,并且参数不是可选的,所以void ExportAnimation( CAnimation const & )就足够了。优点是从接口中可以清楚地看出该方法没有内存管理问题,它只会使用传递的对象并保持原样。在这种情况下,传递原始指针(如在您建议的代码中)比传递引用更糟糕,因为不清楚是否ExportAnimation负责删除传入的对象。

它是否保留对象以供以后使用?

如果函数启动线程以在后台导出动画,则可能是这种情况。在这种情况下,必须清楚参数的生命周期必须超出调用的持续时间。这可以通过shared_ptr在函数中和函数外部使用 --both 来解决 -- 因为它们传达了对象是共享的,并且将尽可能多地保持活动所需的含义。否则,您实际上可以转让所有权。

在后一种情况下,如果执行所有权转移,那么初始代码就可以了——签名在所有权转移中是明确的。否则,您可以选择记录行为,更改为原始指针并通过调用ExportAnimation( myAnimation.release() ).

您添加了一些担忧作为对另一个答案的评论:

我真的可以在方法调用后看到该对象不再存在吗?

调用者在调用auto_ptr中被重置为 0,因此任何取消引用都将成为错误,并将在您尝试的第一个测试中被标记。

我需要查看头文件以查看参数类型是 auto_ptr 而不是普通指针。

您不需要查看标头...只需尝试传递一个原始指针,编译器会告诉您它需要一个auto_ptr<>-- 没有从原始指针到auto_ptr.

我希望该对象存在,直到 auto_ptr 超出范围。

auto_ptr与 不同,标准boost::scope_ptr没有那种语义。对象的所有权可以被释放或传递给 other auto_ptr,因此假设一个对象在 anauto_ptr的整个范围内都存在,这auto_ptr本身就是不好的。

于 2010-08-09T12:29:21.043 回答
3

如果您仅将其内部用作存储位置,那么自动指针的意义何在?

是的,将它传递给函数。或者完全取消它,如果你真的不想要它。大概该功能需要它将所有权传递给其他东西。

听起来您正在寻找的替代方案可能要简单得多:

void ClassA::ExportAnimation(CAnimation &animation) // no pointer

// calling method:
void classB::someMethod()
{
  CAnimation animation(1,2); // no pointer
  ClassA classAInstance;
  classAInstance.ExportAnimation(animation) // no ownership tranfer
  ... do some more stuff
  // object dies here, no earlier, no later
}
于 2010-08-09T12:04:28.260 回答
1

将智能指针传递给ExportAnimation清楚地记录并强制执行所有权已传递给函数,调用者无需删除动画。该函数也不需要显式删除对象,只需让指针超出范围即可。

你的建议很模棱两可;应该ExportAnimation删除您通过原始指针传递的对象吗?您需要检查函数的文档以了解调用者应该做什么,并检查实现以确保它实际上按照文档实现。

我总是建议使用智能指针(和其他 RAII 习惯用法)来使对象生命周期显式和自动。

于 2010-08-09T12:06:10.987 回答