函数采用std :: auto_ptr <base />,可以接受std :: auto_ptr <derived> </derived>

时间:2014-01-10 12:19:44

标签: c++ auto-ptr

我正在尝试创建一个需要auto_ptrBase类的函数,我想用auto_ptrDerived类来调用它。但是我没能完成它。

我尝试过使用它而没有引用:

void function(std::auto_ptr<Base> ptr);

std::auto_ptr<Derived> derivedPtr( new ... )
function(derivedPtr); // error:  #348: more than one user-defined conversion from
                      // "std::auto_ptr<Derived>" to "std::auto_ptr<Base>" applies

并参考:

void function(std::auto_ptr<Base>& ptr);

std::auto_ptr<Derived> derivedPtr( new ... )
function(derivedPtr); //error:  #304: no instance of overloaded function "function" 
                      // matches the argument list

编辑: 我知道auto_ptr已弃用,但我只能访问C++03且无法访问boost。所以如果答案将集中在问题本身上,我将不胜感激:)我也理解采用引用的函数和按值的auto_ptr的区别。在我的实际代码中,该函数取得了auto_ptr的所有权,因此如果我可以从Derived转换为Base工作,则两者都可以。

3 个答案:

答案 0 :(得分:5)

您正在尝试auto_ptr按值和参考,这是完全不同的事情。按值调用意味着,您将所有权转移到函数中,因为auto_ptr在复制时执行此操作。通过引用调用意味着函数外只有auto_ptr来保持所有权。

由于这种差异非常不直观,{2011年标准中已经弃用了auto_ptr,作者一直在劝阻使用auto_ptr更长时间。简而言之:

根本不要使用auto_ptr

如果要将所有权转移到函数中,请使用unique_ptr;如果要将其保留在函数外部,请使用引用或普通指针。这取决于你的实际情况。

更新,因为你提到你必须在不使用boost的情况下使用C ++ 03,所以有一个针对C ++ 03的unique_ptr实现:http://howardhinnant.github.io/unique_ptr03.html 它使用了一些可以轻松手写的增强功能,因此无需使用增强功能即可将其移植到平台上。

答案 1 :(得分:4)

你可以毫不含糊地投射:

function(static_cast<std::auto_ptr<Base> >(derivedPtr));

请注意,要使其正常工作,Base必须具有虚拟析构函数。否则代码具有未定义的行为。

模棱两可的原因就像Arne在他的回答中所说的那样 - 调用者对function是否接受值或引用并不明显,因此对于调用者来说,他们的{{1}是否不明显将通过调用释放或不释放,如果它被释放,它是否被转换为可以正确auto_ptr指针的类型。模棱两可的转换AFAIK就是为了阻止你编写这么难的代码。通过强制转换,您可以在delete被释放的调用代码中明确显示它。

答案 2 :(得分:1)

手动管理内存比使用auto_ptr更好,因为它的使用非常充满错误。

最好使用工业强度替代:最糟糕的是,检查自由主义boost liscense并确定你是否可以编写自己的克隆。

失败,写下你自己的替换owning_ptr。同时创建ownomg_ptr_transfer班级template。在owning_ptr上阻止复制构造构造,从owning_ptr_transfer启用隐式转换,该转换采用底层限制。有一个自由的函数或方法将底层指针移动到传输对象。

从本质上讲,如果必须,请使用C ++ 03编写自己的unique_ptr

如果您不使用别人的解决方案,也不会自己编写解决方案,那么只需手动操作内存即可。 auto_ptr不值得:与unique_ptr相比,它不仅仅是次优的,它实际上是有害的:它的目的是使内存管理更容易,而且它更容易出错。这是一次实验,但失败了。