考虑我最近在代码库中看到的以下示例代码:
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
}
但这确实是一个问题?
答案 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习语)来使对象生命周期显式和自动化。