代码复习问题 - 我应该允许将auto_ptr作为参数传递吗?

时间:2010-08-09 11:56:18

标签: c++ coding-style auto-ptr

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

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 个答案:

答案 0 :(得分:4)

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

答案 1 :(得分:4)

这完全取决于ExportAnimation是什么以及如何实施。

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

然后转换为引用并传递实际引用。没有必要传递成员资格,参数不是可选的,因此void ExportAnimation( CAnimation const & )就足够了。优点是从界面可以清楚地看出该方法没有内存管理问题,它只是使用传递的对象并保留它。在这种情况下,传递原始指针(如在您的建议代码中)要比传递引用要差得多,因为不清楚ExportAnimation是否负责删除传入的对象。

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

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

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

您在另一个答案中添加了一些注意事项:

  

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

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

  

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

你不需要查看标题...只是尝试传递一个原始指针,编译器会告诉你它需要auto_ptr<> - 没有从原始指针到{{1的隐式转换}}

  

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

auto_ptr不同,标准auto_ptr没有这种语义。对象的所有权可以被释放或传递给其他boost::scope_ptr,因此假设auto_ptr中的对象生活在auto_ptr的整个范围内本身就是坏事。 / p>

答案 2 :(得分:3)

如果您只将内部用作存储位置,那么auto-ptr的重点是什么?

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

听起来你正在寻找的替代方案可能更简单:

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
}

答案 3 :(得分:1)

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

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

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