V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
ruokw
V2EX  ›  问与答

c++中引用和智能指针的简单问题

  •  
  •   ruokw · 2021-02-04 17:20:51 +08:00 via Android · 1497 次点击
    这是一个创建于 1378 天前的主题,其中的信息可能已经有所发展或是发生改变。
    传入对象引用,例如 json-value ( A )。现在想把它包装成新对象( B{A})返回,但是底层指向同一个对象。而且 B 要支持无参构造。使用智能指针去包装 A 会出现超过域后过早释放空间的问题。想问下这种情况下有什么好的解决方法吗?
    第 1 条附言  ·  2021-02-04 18:31:30 +08:00
    B f(A& a)
    {
    B b;
    b.a=shared_ptr<A>(&a);
    return b;
    }

    void m(A& a)
    {
    {
    B b=f(a);
    (*b.a)=xxx;
    }
    print a; // error
    return ;
    }
    第 2 条附言  ·  2021-02-04 21:04:14 +08:00
    谢谢大家了,后来想想也是,不让智能指针管理生命周期,就直接用 raw 指针就行了。蠢了,逃~ 哈哈
    23 条回复    2021-02-04 22:23:03 +08:00
    yianing
        1
    yianing  
       2021-02-04 17:39:39 +08:00 via Android
    那在有参构造的时候传入智能指针的拷贝不就行了吗?
    ruokw
        2
    ruokw  
    OP
       2021-02-04 17:50:37 +08:00 via Android
    @yianing 现在问题是 A 应该是在 B 之后才会被释放,但是 B 保存 A 的智能指针,在 B 死亡时会提前释放掉 A 。
    yianing
        3
    yianing  
       2021-02-04 18:12:58 +08:00 via Android
    @ruokw B 死亡时只会将 A 的引用数减一,并不会释放掉指针指向的内存吧,只有引用数变为 0 的时候才会真正释放内存
    wutiantong
        4
    wutiantong  
       2021-02-04 18:19:10 +08:00
    你没有描述清楚你的问题
    ruokw
        5
    ruokw  
    OP
       2021-02-04 18:31:55 +08:00 via Android
    @wutiantong 补充了
    ruokw
        6
    ruokw  
    OP
       2021-02-04 18:32:02 +08:00 via Android
    @yianing 补充了
    wevsty
        7
    wevsty  
       2021-02-04 18:51:30 +08:00
    首先把传入的引用转换为智能指针是一种强烈不推荐的做法。
    其次,shared_ptr 在超过生存周期的时候会自动对引用计数减 1,如果引用计数为 0 就会去 delete 管理的对象。如果不想 shared_ptr 指针去 delete 这个对象,要不然增加引用计数,要不然就延长 shared_ptr 的生存周期。
    yianing
        8
    yianing  
       2021-02-04 19:03:34 +08:00 via Android
    好家伙,都用智能指针了为什么还要去获取裸指针呢?
    ruokw
        9
    ruokw  
    OP
       2021-02-04 19:04:16 +08:00 via Android
    @wevsty 这个能明白。现在的问题是实际上 B 被作为类型的集合,用来统一一类函数的返回类型,B{int string long A},如果 B 里面 A 用引用,就又意味着 B 不能无参构造了。 所以现在有啥好的方法? 还是说只能整个重新设计?
    ruokw
        10
    ruokw  
    OP
       2021-02-04 19:09:11 +08:00 via Android
    @yianing 你是说 shared_ptr(&a)么? 至少我现在在 mxvc2011 里面对引用 a 构造智能指针要用&a 。这点也比较难理解,为啥引用还有指针?
    yianing
        11
    yianing  
       2021-02-04 19:12:50 +08:00 via Android
    @ruokw 智能指针创建的正确使用姿势是 std::make_shared,你这把传进来的实例引用取地址绝对有问题啊🌚🌚
    imjamespond
        12
    imjamespond  
       2021-02-04 19:36:09 +08:00 via Android
    可以用 weak ptr 啊。。。
    ruokw
        13
    ruokw  
    OP
       2021-02-04 19:38:42 +08:00 via Android
    @yianing 这个也能明白,但是现在情况是 B 不仅包装包装 a 而是包装 a 的子对象比方说 a 是 json::Value ,b=shared_ptr(a["num"])。 这时候可能光 a 是智能指针都不够
    ruokw
        14
    ruokw  
    OP
       2021-02-04 19:39:56 +08:00 via Android
    @imjamespond 用 weak 还是得先有 shared 哈,有 shared 就又回到最初的说的了
    hazardous
        15
    hazardous  
       2021-02-04 19:53:17 +08:00
    使用 shared_ptr 第二个参数:自定义 deletor
    hazardous
        16
    hazardous  
       2021-02-04 20:02:23 +08:00
    还有个问题是很难保证传入 A 的引用一定是 new 出来的对象,如果是个栈上对象那 shared_ptr 释放的时候就崩了。
    ruokw
        17
    ruokw  
    OP
       2021-02-04 20:08:01 +08:00 via Android
    @hazardous 我把 deletor 设置成空,最原始的 a 在栈上,现在只是说用智能指针代替引用。在我现在这个场景应该够用了。谢谢你了哈😄
    wutiantong
        18
    wutiantong  
       2021-02-04 20:40:01 +08:00
    楼主这 c++纯属瞎写啊。。。

    首先我们有 enable_shared_from_this ( https://en.cppreference.com/w/cpp/memory/enable_shared_from_this ),
    其次我们有 aliasing constructor for shared_ptr ( https://en.cppreference.com/w/cpp/memory/shared_ptr/shared_ptr #8 )
    mainjzb
        19
    mainjzb  
       2021-02-04 20:55:30 +08:00
    ..你已经把生死权交给 b 了。
    所以 b 死了,拉着 a 一起死很正常。
    不想交给 b 就用普通指针。所以用智能指针的意义何在。
    ruokw
        20
    ruokw  
    OP
       2021-02-04 20:55:44 +08:00 via Android
    @wutiantong 哈哈 新手上路嘛,我看看你说的哈
    mainjzb
        21
    mainjzb  
       2021-02-04 20:56:34 +08:00
    要么 a 从一开始就用 share 指针。
    要么自己管理,都不用智能指针
    ruokw
        22
    ruokw  
    OP
       2021-02-04 21:02:06 +08:00 via Android
    @mainjzb 后来想想也是。。。蠢了╰(*´︶`*)╯ 哈哈
    nicebird
        23
    nicebird  
       2021-02-04 22:23:03 +08:00
    初学者吧,低级错误。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5848 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 02:38 · PVG 10:38 · LAX 18:38 · JFK 21:38
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.