2015-11-02 65 views
0

[一个答案,下面是给力.release().get()之间进行选择,可悲的是错误的一般建议是只使用.get()]重温原因


摘要:这问题是要求技术原因或行为原因(可能是基于经验),为什么诸如unique_ptr之类的智能指针被剥离了指针的主要特征,即10,即在需要指针的地方(C API's)传递的能力, 。

我已经研究过这个话题,并且引用了下面两个主要的原因,但这些看起来似乎没有任何效果。

但是我的傲慢并不是无边无际的,我的经验并没有那么广泛以至于说服我说我一定是对的。

这可能是unique_ptr不是设计哑C API指针的简单生命周期管理为主要用途,当然这提出了unique_ptr发展不会[http://bartoszmilewski.com/2009/05/21/unique_ptr-how-unique-is-it/],但是unique_ptr声称自己是“什么样的auto_ptr应该是”(但是,我们不能用C++ 98)” [http://www.stroustrup.com/C++11FAQ.html#std-unique_ptr]但也许这不是一个主要用途的auto_ptr任。


我使用unique_ptr对于一些C API资源管理和震惊[是的,令人震惊的:-)]发现所谓的智能指针几乎不像指针那样。

API的我使用期望指针,而我真的不想在所有地方加上.get()。这一切都使得智能指针unique_ptr看起来很愚蠢。

什么是当前推理unique_ptr不会自动转换为其转换为该指针类型时所保持的指针吗?

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++编码器不会理解如何使用指针,或者会忘记遵守它吗?如果我用智能指针发生错误,它会默默地编译和行为就像它与哑指针一样?[当然这样的说法没有结束,我会忘记的>->]

对于在后的另一点,我不是更容易写delete b比我写delete b.get(),虽然这似乎是一个(可能是因为遗留代码转换),并且讨论了C++ "smart pointer" template that auto-converts to bare pointer but can't be explicitly deleted然而,1996年的Meyers歧义,在http://www.informit.com/articles/article.aspx?p=31529&seqNum=7中提到,似乎通过定义演员阵容void*以及T*以便delete不能解决哪个问题投入使用。

delete问题似乎有一定的合法性,因为它很可能移植一些旧代码时是一个真正的问题,但它似乎连前迈耶得到很好的解决(http://www.boost.org/doc/libs/1_43_0/libs/smart_ptr/sp_techniques.html#preventing_delete

是否有更多的技术来拒绝智能指针的基本指针行为?或者当时的理由看起来很吸引人?

上讨论包含坏事[Add implicit conversion from unique_ptr<T> to T*Why doesn't `unique_ptr<QByteArray>` degrade to `QByteArray*`?C++ "smart pointer" template that auto-converts to bare pointer but can't be explicitly deletedhttp://bartoszmilewski.com/2009/05/21/unique_ptr-how-unique-is-it/]但没有一般警告特定的,或者说是不是使用非智能C指针,以C API的任何恶化。

针对编码人员隐含的风险进行衡量时,盲目地在每个地方添加.get(),并获得它们应该受到保护的所有相同危害使得整个限制看起来非常不合时宜。


在我的情况,我用了两个铸件Meyer的伎俩,并采取伴随的风险隐患,希望读者能够帮帮我知道它们是什么。

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

using RIP_ptr = unique_dptr<RIP, d_type(::RIP_free)>; 
RIP_ptr rip1(RIP_new_bitmap("/tmp/test.png")); 

没有,这是一个智能指针,我可以使用。 *我曾经宣布当智能指针类型被定义 *我可以通过它周围像一个指针 *当范围死

是的,我错误地使用API​​和泄漏拥有引用它被解放了free功能,但.get()不会停止,尽管这是不方便的。

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

+1

它认为这是公平的说,有广泛的2种方法来编写软件 - 方便和安全。看来,安逸总是以牺牲安全为代价,反之亦然。 C++委员会强烈推动C++向安全和决定论的方向发展。据推测,他们认为,为了表达简单,可以使用更宽松的语言。 –

+0

我认为你就在那里。我正在寻找关于不得不添加'.get()'的观点的信息*'更安全'*更安全* –

+1

他们的意思是你必须*故意*做这个危险的事情。你无法通过隐式演员意外地做到这一点(一个没有经验或者疲惫的开发者可能不会注意到)。正如你所知,抓住指针是拿着手榴弹的针被取出。标准人士认为这是人们应该知道他们正在做的事情:-) –

回答

3

一个答案,我很惊讶,我还没有在我的搜索中发现的文档中隐含unique_ptr::release [http://en.cppreference.com/w/cpp/memory/unique_ptr/release]

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

由此推断,get()是通过无主参考

作为一双,这些功能解释为什么自动脱引用不允许相应的功能;编码器被迫取代每个指针使用或者.release()或者.get(),这取决于被调用函数如何处理指针。

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

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

不幸的是,如果编码器的唯一建议是使用.get(),那么这种策略是无效的;编码器不知道选项,并且错过了使他的代码安全和清楚的机会。