C++智能指针的正确使用方式 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
cyhone
V2EX    C++

C++智能指针的正确使用方式

  •  
  •   cyhone 2019-10-05 13:18:11 +08:00 6488 次点击
    这是一个创建于 2262 天前的主题,其中的信息可能已经有所发展或是发生改变。

    C++11 中推出了三种智能指针,unique_ptr、shared_ptr 和 weak_ptr,同时也将 auto_ptr 置为废弃(deprecated)。

    但是在实际的使用过程中,很多人都会有这样的问题:

    • 不知道三种智能指针的具体使用场景
    • 无脑只使用 shared_ptr
    • 认为应该禁用 raw pointer(裸指针,即 Widget*这种形式),全部使用智能指针

    本文试图理清楚三种智能指针的具体使用场景,并讲解三种智能指针背后的性能消耗。同时也解释了为什么要用 sharedfrom_this 以及智能指针的函数传参问题。

    点击查看原文

    9 条回复    2019-10-15 18:54:33 +08:00
    luolikon
        1
    luolikon  
       2019-10-06 11:49:17 +08:00 via iPhone
    写得不错,但感觉在哪看过
    classyk
        2
    classyk  
       2019-10-06 22:49:28 +08:00
    实际使用中 unique_ptr 基本被忽略。能用 unqiue_ptr 的地方,shared_ptr 性能也够了,实在不行上 weak_ptr
    heiheidewo
        3
    heiheidewo  
       2019-10-06 23:41:00 +08:00
    webrtc 里面几乎全是 unique_ptr,虽然用 shared_ptr 可以替代 unique_ptr,但是 unique_ptr 可以从机制上迫使程序员了解变量的调用流程
    macha
        4
    macha  
       2019-10-07 15:13:29 +08:00
    shared_from_this 还可以解决 bind 类成员函数作为回调函数时,对象被析构的问题。
    cyhone
        6
    cyhone  
    OP
       2019-10-08 19:12:53 +08:00
    @classyk unqiue_ptr 和 shared_ptr 是两种不同的使用场景,用对两种指针会让代码语义更加鲜明,也更加优雅
    wutiantong
        7
    wutiantong  
       2019-10-09 10:34:55 +08:00
    智能指针的正确用法大概就是渐渐认识到它们是冗余的。
    wutiantong
        8
    wutiantong  
       2019-10-09 10:36:17 +08:00
    大部分人在智能指针方面最大的错误是滥用。
    FrankHB
        9
    FrankHB  
       2019-10-15 18:54:33 +08:00   1
    智能指针不止是 std 给你的那坨。

    没有所有权的指针语义上更清楚的是 observer_ptr (如果不需要 nullable,那直接引用,包括 & 、&& 或者 std::reference_wrapper 或者其它什么类似物)。这种做法唯一的缺陷就是罗嗦,但这是语言设计本来的问题谁叫内建指针这种责任不明确的垃圾占用了 * 这样的更简洁的语法呢(即便 * 这种语法本来就很不咋地)?注意,如果要求是像样的而不是容易让实现偷懒的设计,原则上混淆使用目的的内建指针就不应该直接在高级语言中提供: https://github.com/FrankHB/pl-docs/blob/master/zh-CN/why-is-pointer-awful.md
    内建的指针因为兼容包袱永远不可能更清楚,所以和 LZ 的提法相反,就是应该能禁用就禁用,而体现不得不用和可以被其它类型取代时的区别。事实上:根本意义上只有一种情况才必须使用内建的指针互操作,例如内联汇编需要依赖二进制兼容,或者 new 这种从核心语言特性钦定返回内建指针的情形的变通(本质上,返回内建指针仍然是个目无所有权的糟粕设计,仅仅因为 T* 是内建语法就凌驾于去任意地复用而不是提供特设的 new_ptr<T> 或者干脆直接返回现代意义的 unique_ptr<T> ,这种选择根本没什么逻辑性,而且是个后患无穷的做法;只不过当年 C++ 还没模板也没 move copy-initialization,这种垃圾设计就当历史包袱忍了算了)。使用内建指针根本不能区分不得不用内建指针和允许使用 observer_ptr 的情形,仍然削弱了目的性。
    题外话,BS 是反对 observer_ptr 的: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1408r0.pdf 。不过,根本上他的理由站不住脚,一部分就是上面的原因(另一部分问题是关于语言特性历史包袱的理解和 WG21 整体对核心语言设计演进方向控制上的普遍无能)。

    有所有权的情形在 unique_ptr 之前首先考虑直接传值。(至少还得清楚没法表达 __restrict 的情形下没事用指针 /引用永远是被坑的。)

    shared_from_this 有的坑是因为 weak_ptr 被滥用:
    https://stackoverflow.com/questions/39653239
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2705 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 28ms UTC 14:15 PVG 22:15 LAX 06:15 JFK 09:15
    Do have faith in wha you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86