我有一个方法可以在auto_ptr
中创建一个对象,将auto_ptr
粘贴到vector
中,然后返回一个指向该对象的原始指针。
这种设计的问题是它返回一个原始指针。调用者很容易误解这个指针是非拥有的,并将此调用的结果包装到托管指针中,这会在内存获得双重释放时导致内存访问冲突。
int main (void)
{
{
std::auto_ptr<int> foo = ThisMethodReturnsNonOwningPtr(); // Uhoh
}
ThisMethodUsesThePtr(); // Crash
return 0;
}
理想情况下,我想返回类似指针的东西,这些指针无法转换为托管指针,所以我不必担心调用者会这样做。
或者,我可能只是将一个索引返回到数组中,但是真正方便的是能够传递指针,并且谁知道我最终可能会稍后改组或排序数组。
答案 0 :(得分:1)
停止使用auto_ptr并开始使用unique_ptr或shared_ptr。后者具有引用计数,因此您可以安全地返回对象,而其他人可以使用它。在所有引用都被释放之前,它指向的数据不会被释放。
如果您需要安全地返回指向对象的指针并且仍然能够更改向量,则没有其他选择。您可以使用unique_ptr来阻止调用者将返回的指针视为拥有它。
最后的方法是对代码发表评论,说明向量拥有对象,指针只是为了方便起见。它不如让编译器检查调用代码那么好,但如果你像上面提到的那样限制选项,它可能是唯一的方法。
答案 1 :(得分:1)
创建一个包装类模板raw_ptr<T>
,它封装了T*
。
如果现在实现operator*
和operator->
但没有转换运算符,则无法再将此指针指定给另一个智能指针,因为该指派需要两次自定义转换(raw_ptr<T>
→ T*
→smart_ptr<T>
),这在C ++中是不允许的。
请注意,正如其他人所说,你应该不使用auto_ptr<T>
- 这是deprecated的原因。请改用std::unique_ptr<T>
。首先,you cannot actually safely stick auto_ptr
s into a std::vector
,必须非常小心,不要意外地复制(并因此使这些指针无效)。
答案 2 :(得分:1)
首先,如果你可以将auto_ptr粘贴到矢量中,那么现在是时候了
升级您的编译器或库。这不合法
自1998年第一个标准以来。如果你有C ++ 11,你可以
使用std::unique_ptr
;如果没有,你需要保留原始指针
在向量中。在这两种情况下,您都希望包装矢量:
使用std::unique_ptr
,以便客户不必这样做
任何想要获得实际指针的东西,以及原始指针,
这样您就可以管理与它们相关的内存。
对于其余的,只需返回一个原始指针。如果你有 程序员绕过删除随机指针,你就沉没了 无论如何;大部分时间,原始指针用于导航,和 同样可能指向具有静态生命周期的对象 其他任何事情。
答案 3 :(得分:0)
如果您不希望使用delete运算符以常规方式删除该对象,则可以将该类的析构函数设为private,并实现自毁该对象的destroy()函数。
如果你能让函数返回类似shared_ptr的东西,那就更好了。
第三个选项可能只是让一个类像函数返回的template<typename> struct non_ownership_ptr;
而不是原始指针。这个指针类只保存指针,你必须明确地使用auto_ptr<T> p=foo().non_owned_ptr;
来避免(或至少减少)意外分配给auto_ptr等。
答案 4 :(得分:0)
我总是不愿意写出依赖于提升的答案,因为不是每个人都可以使用它而且只是为了一件小事而把它拉进来几乎总是有点过分,但是如果你还有它,你可以返回一个{ {1}}。从表面上看,它似乎不是可选参考可以工作,但它(大多数情况下)确实有效。请参阅boost's documentation。
这将为您提供所需的可空性(返回boost::optional<&>
以指示错误),同时非常清楚调用者不会取得对象的所有权。