gpt4 book ai didi

c++ - 再谈在智能指针上不进行隐式转换的原因

转载 作者:行者123 更新时间:2023-11-30 02:35:35 38 4
gpt4 key购买 nike

[一个答案,以下是在.release().get()之间进行选择,可悲的是,错误的一般建议是仅使用.get()]

摘要:这个问题是出于技术原因或行为原因(可能基于经验),为什么要删除诸如unique_ptr之类的智能指针的主要特性,即希望传递指针的能力( C API)。

我已经研究了该主题,并在下面列举了两个主要主张的理由,但是这些理由似乎无效。

但是我的傲慢不是无止境的,我的经历也没有使我相信我必须是对的。

可能不是将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是Expected指针,而实际上是,我不想在各处添加.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,但Meyers于1996年含糊 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()并获得原本应该受到保护的所有相同危害的隐含风险,使得整个限制似乎非常不值得。

在我的案例中,我使用了迈耶的两次演技技巧,并承担了随之而来的潜在风险,希望读者能帮助我知道它们是什么。
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"));

不,那是我可以使用的智能指针。
*当定义智能指针类型时,我一次声明 free函数
*我可以像指针一样传递它
*示波器死后释放

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

也许我应该在其中添加一些 const,以表示缺乏所有权转移。

最佳答案

unique_ptr::release [http://en.cppreference.com/w/cpp/memory/unique_ptr/release]]的文档中暗含了一个我在搜索中找不到的答案。
release()返回指针,然后unique_ptr然后引用nullptr,因此很明显,它可以用于将拥有的引用传递给不使用智能指针的API。

通过推论,get()是传递无人引用的对应函数

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

因此,编码人员被迫采取明智的行动,选择一种行为或另一种行为,并升级遗留代码以使其更加明确和安全。
.get()是一个奇怪的名字,但是这种解释对我来说很有意义。

可悲的是,如果编码人员唯一的建议是使用.get(),则此策略无效。编码人员没有意识到选择的余地,因此错过了使代码安全清晰的机会。

关于c++ - 再谈在智能指针上不进行隐式转换的原因,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33475645/

38 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com