【问题标题】:What is the difference between an empty and a null std::shared_ptr in C++?C++ 中的空 std::shared_ptr 和空 std::shared_ptr 有什么区别?
【发布时间】:2014-09-18 19:16:55
【问题描述】:

cplusplus.com shared_ptr page 区分了 empty std::shared_ptrnull shared_ptrcppreference.com page 没有明确指出区别,但在描述 std::shared_ptr 行为时使用了“空”和与 nullptr 的比较。

shared_ptr 和空shared_ptr 有区别吗?这种混合行为指针有什么用例吗?非空 null shared_ptr 是否有意义?在正常使用中(即,如果您没有明确构造一个)是否会出现最终得到一个空但非空的 shared_ptr 的情况?

如果您使用的是 Boost 版本而不是 C++11 版本,这些答案是否会发生变化?

【问题讨论】:

    标签: c++ c++11 shared-ptr


    【解决方案1】:

    这是shared_ptr 行为的一个奇怪角落。它有一个构造函数,允许您创建一个shared_ptr,该shared_ptr 拥有一些东西并指向其他东西:

    template< class Y > 
    shared_ptr( const shared_ptr<Y>& r, T *ptr );
    

    使用此构造函数构造的shared_ptr r 共享所有权,但指向 ptr 指向的任何内容(即调用get() 或@ 987654331@ 将返回ptr)。这对于ptr 指向r 拥有的对象的子对象(例如,数据成员)的情况很方便。

    您链接的页面调用shared_ptr,它什么都不拥有empty,而shared_ptr 则不指向任何东西(即其get() == nullptrnull。 (Empty 在这个意义上被标准使用;null 不是。)你可以构造一个 null-but-not-empty shared_ptr,但它不会' t 很有用。一个空但非空的shared_ptr 本质上是一个非拥有指针,它可以用来做一些奇怪的事情,比如passing a pointer to something allocated on the stack to a function expecting a shared_ptr(但我建议先把shared_ptr 放入API 中的人打孔)。

    boost::shared_ptr 也称为has this constructor,他们称之为别名构造函数

    【讨论】:

    • 值得注意的是:C++11 § 20.7.2.2.1 (p16) "注意:此构造函数允许创建一个空的 shared_ptr 实例,其具有非 NULL存储的指针。”还值得一提的是前面的注释 (p15),“为避免出现悬空指针的可能性,此构造函数的用户必须确保 p 至少在 r 的所有权组被销毁之前保持有效。”确实很少使用的结构。
    • @Cubbi A shared_ptr,其get() 返回nullptr确实比较等于nullptr,无论它是否拥有任何东西。
    • 一个空但非空的shared_ptrs 可以很有用,以确保在所有拥有的指针都超出范围时执行某些函数(即使在例外!)。不确定,现在是否有专门的课程。
    • @coldfix 一个空但非空的shared_ptr 能做什么非空非空shared_ptr 不能?
    • 别名构造函数源自 Bloomberg,并在 Boost 中实现之前被提议用于标准(参见 N1851)。我更喜欢标准中的术语“与r 共享所有权”,而不是“拥有r 拥有的任何东西”
    【解决方案2】:

    空的和空的 shared_ptr 有区别吗?

    shared_ptr 没有控制块,它的使用计数被认为是0。空shared_ptr 的副本是另一个空shared_ptr。它们都是独立的shared_ptrs,不共享公共控制块,因为它们没有。空的shared_ptr 可以使用默认构造函数构造,也可以使用采用nullptr 的构造函数构造。

    非空 null shared_ptr 具有可以与其他 shared_ptrs 共享的控制块。非空 null shared_ptr 的副本是shared_ptr 与原始shared_ptr 共享相同的控制块,因此使用计数不为0。可以说shared_ptr 的所有副本共享相同的@987654335 @。非空 null shared_ptr 可以用对象类型的空指针构造(不是nullptr

    示例如下:

    #include <iostream>
    #include <memory>
    
    int main()
    {
        std::cout << "std::shared_ptr<int> ptr1:" << std::endl;
        {
            std::shared_ptr<int> ptr1;
            std::cout << "\tuse count before copying ptr: " << ptr1.use_count() << std::endl;
            std::shared_ptr<int> ptr2 = ptr1;
            std::cout << "\tuse count  after copying ptr: " << ptr1.use_count() << std::endl;        
            std::cout << "\tptr1 is " << (ptr1 ? "not null" : "null") << std::endl;
        }
        std::cout << std::endl;
    
        std::cout << "std::shared_ptr<int> ptr1(nullptr):" << std::endl;
        {
            std::shared_ptr<int> ptr1(nullptr);
            std::cout << "\tuse count before copying ptr: " << ptr1.use_count() << std::endl;
            std::shared_ptr<int> ptr2 = ptr1;
            std::cout << "\tuse count  after copying ptr: " << ptr1.use_count() << std::endl;        
            std::cout << "\tptr1 is " << (ptr1 ? "not null" : "null") << std::endl;
        }
        std::cout << std::endl;
    
        std::cout << "std::shared_ptr<int> ptr1(static_cast<int*>(nullptr))" << std::endl;
        {
            std::shared_ptr<int> ptr1(static_cast<int*>(nullptr));
            std::cout << "\tuse count before copying ptr: " << ptr1.use_count() << std::endl;
            std::shared_ptr<int> ptr2 = ptr1;
            std::cout << "\tuse count  after copying ptr: " << ptr1.use_count() << std::endl;        
            std::cout << "\tptr1 is " << (ptr1 ? "not null" : "null") << std::endl;
        }
        std::cout << std::endl;
    
        return 0;
    }
    

    它输出:

    std::shared_ptr<int> ptr1:
        use count before copying ptr: 0
        use count  after copying ptr: 0
        ptr1 is null
    
    std::shared_ptr<int> ptr1(nullptr):
        use count before copying ptr: 0
        use count  after copying ptr: 0
        ptr1 is null
    
    std::shared_ptr<int> ptr1(static_cast<int*>(nullptr))
        use count before copying ptr: 1
        use count  after copying ptr: 2
        ptr1 is null
    

    http://coliru.stacked-crooked.com/a/54f59730905ed2ff

    【讨论】:

    猜你喜欢
    • 2013-04-16
    • 1970-01-01
    • 2013-08-24
    • 2020-08-12
    • 2017-08-13
    • 1970-01-01
    • 2011-10-29
    • 1970-01-01
    相关资源
    最近更新 更多