首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >重新分析智能指针没有隐式转换的原因

重新分析智能指针没有隐式转换的原因
EN

Stack Overflow用户
提问于 2015-11-02 10:38:31
回答 1查看 225关注 0票数 1

下面的一个答案是在.release().get()之间强制做出选择,遗憾的是,错误的一般建议是只使用.get()

摘要:这个问题是出于技术原因,或者行为原因(可能是基于经验),为什么智能指针(如unique_ptr )被剥夺了指针的主要特性,即在需要指针的地方传递的能力(C )。

我已经研究过这个问题,并列举了以下两个主要的理由,但这些理由似乎不成立。

但我的傲慢并不是无止境的,我的经验也不够广泛,以至于我相信我一定是对的。

也许unique_ptr不是设计简单的生命周期管理的哑C API指针作为主要用途,当然,这个提议的unique_ptr开发不会是ptr-how-unique-is-it/],但是unique_ptr声称是“auto_ptr应该是什么”(但我们不能用C++98编写)“ptr]”,但也许这也不是auto_ptr的主要用途。

我使用unique_ptr来管理一些C资源,并且震惊地发现,所谓的智能指针根本就不像指针。

我使用的API是expect指针,我真的不想在所有地方添加.get()。这一切都使智能指针unique_ptr显得相当愚蠢。

unique_ptr被转换为该指针的类型时,它不自动转换为它所持有的指针,其当前的推理是什么?

代码语言:javascript
复制
void do_something(BLOB* b);
unique_ptr<BLOB> b(new_BLOB(20));

do_something(b); 
// equivalent to do_something(b.get()) because of implicit cast

我读过http://herbsutter.com/2012/06/21/reader-qa-why-dont-modern-smart-pointers-implicitly-convert-to/,而且它(考虑到作者)实际上并没有令人信服地回答这个问题,所以我想知道是否有更多真实的例子或技术/行为的理由来证明这一点。

为了参考本文的示例,我没有尝试do_something(b + 42),也没有在我所指向的对象上定义+,因此*b + 42没有意义。

但是如果是这样的话,如果我是认真的,那么我实际上会输入*b + 42,如果我想在指针中添加42,我会输入b + 42,因为我期望我的智能指针实际上是一个指针。

让智能指针变得哑口无言的一个原因,真的是担心C++编码器不会理解如何使用指针,或者总是忘记遵守指针吗?如果我用一个智能指针出错,它就会像对一个哑指针那样默默地编译和运行?毫无疑问,这种争论是无止境的,我可能忘记了> in ->

关于文章中的另一点,我编写delete b的可能性并不比编写delete b.get()的可能性大,尽管这似乎是一个常见的原因(可能是因为遗留代码转换),并讨论了C++ "smart pointer" template that auto-converts to bare pointer but can't be explicitly deleted --然而,http://www.informit.com/articles/article.aspx?p=31529&seqNum=7中提到的1996年Meyers的含糊不清之处--定义了void*T*的强制转换,这样delete就无法确定该使用哪种转换。

delete问题似乎具有一定的合法性,因为在移植一些遗留代码时,它可能是一个真正的问题,但似乎在Meyer (delete)之前就已经很好地解决了这个问题。

是否有更多的技术来拒绝这种基本指针-智能指针的行为?还是当时的原因看起来很有说服力?

以前的讨论中包含了关于不好的事情的一般警告-- ptr-how-unique-is-it/],但是没有什么特别的,或者这比使用非智能C指针指向C更糟糕。

对代码者盲目地添加.get()的隐含风险进行测量的不便性,以及它们应该受到保护的所有相同的危害,使得整个限制看起来非常不值得。

在我的例子中,我使用了Meyer的两种类型的技巧,并承担了随之而来的隐藏风险,希望读者能够帮助我了解它们是什么。

代码语言:javascript
复制
template<typename T, typename D, D F>
class unique_dptr : public std::unique_ptr<T, D> {
    public: unique_dptr(T* t) : std::unique_ptr<T, D>(t, F) { };
    operator T*() { return this->get(); }
    operator void*() { return this->get(); }
};

#define d_type(__f__) decltype(&__f__), __f__

感谢@Yakk提供宏提示(Clean implementation of function template taking function pointerHow to fix error refactoring decltype inside template)

代码语言:javascript
复制
using RIP_ptr = unique_dptr<RIP, d_type(::RIP_free)>;
RIP_ptr rip1(RIP_new_bitmap("/tmp/test.png"));

不,那是我可以用的智能指针。*在定义智能指针类型时,我只声明一次free函数*我可以像指针一样传递它*在作用域死亡时释放它

是的,我可以错误地使用API并泄漏自己的引用,但是.get()并没有阻止它,尽管它带来了不便。

也许我应该有一些const在那里,作为对缺乏所有权转移的一个点头。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-11-02 11:13:57

我惊讶于我在搜索中没有找到的一个答案是在unique_ptr::release ptr/release]的文档中暗示的

release()返回指针和unique_ptr,然后引用nullptr,因此很明显,这可以用于将拥有的引用传递给不使用智能指针的API。

通过推论,get()是传递无主引用的相应函数。

作为一对,这些函数解释了为什么不允许自动去引用;编码器被迫用.release().get()替换每个指针的使用,这取决于被调用的函数将如何对待指针。

因此,编码器被迫采取智能行动,选择一种行为或另一种行为,并升级遗留代码,使之更加明确和安全。

.get()是这个用法的一个奇怪的名字,但是这个解释对我来说很有意义。

可悲的是,如果编码器唯一的建议是使用.get(),那么这种策略是无效的;编码器不知道选择,因此错过了使代码安全和清晰的机会。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33475645

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档