Shared_ptr 未按预期为对象设置实例

Shared_ptr instance is not set for an object as expected

我有一个结构 A,它有另一个结构 C 的成员。所以 A 的成员是 c1Ptr_。 我使用 2 个结构 S 和 N。N 有成员 A,a_,S 有成员 C,c_。 在我实例化 A 并使用创建的 A 对象为 S 创建 a c 对象并将创建的 A 对象传递给 N 之后,我希望 N 中也有 A->c1Ptr_。
谢谢。

 #include <iostream>
    #include <memory>
    using namespace std;
    
    
    
    struct C1 
    {
        C1(int x):x_(x)
        {
            std::cout<<"-C1: x_: " << x_ << std::endl;
        }
        int x_;
        ~C1()
        {
            std::cout<<"-DC1: x_: " << x_ << std::endl;
        }
    };
    
    using C1ptr = std::shared_ptr<C1>;
    
    
    
    struct A
    {
       C1ptr c1Ptr;
    };
    
    
    struct S
    {
       S(C1ptr& c1Ptr):c1Ptr_(c1Ptr)
       {
           
       }
       
       C1ptr c1Ptr_;
    };
    
    struct N
    { 
        N(std::shared_ptr<A> a):a_(a)
        {
            
        }
        std::shared_ptr<A> a_;
    };
    
    
    
    int main()
    {
       std::shared_ptr<A> a = std::make_shared<A>();
       S s(a->c1Ptr);
       N n(a);
       
       s.c1Ptr_ = std::make_shared<C1>(12);
       
       if (n.a_->c1Ptr)
       {
           std::cout<<"c1Ptr is set for N\n";
       }
       else
       {
           std::cout<<"c1Ptr is NOT set for N\n"; // why c1Ptr is not set for n.a_ ? 
       }
    
        return 0;
    }

shared_ptr 不共享指针,它共享指针的所有权。

这意味着您可以更改个人 shared_ptr 以指向其他事物,独立于其他 shared_ptr,但是只要没有 shared_ptr 指向某物,那东西被删除了。可以将其视为向指针添加一个计数器。当您创建、删除或将 shared_ptr 重新分配给 nullptr 以外的其他内容时,您将增加或减少计数器。如果计数器达到 0(通常是在删除时),那么它也会删除指针。

在你的例子中,你正在从 a 复制一个 nullptr。所以你有两个 shared_ptr 都存储 nullptr。然后您更改其中一个以指向一个新事物 (12)。这不会改变内存中的任何其他内容,或者特别是其他 shared_ptrs.

的值

您可以通过绘制对象 asn 及其内容以及它们的内容所指向的内容来尝试自己解决这个问题:

auto a = std::make_shared<A>();  // a(c1Ptr_ = null)
S s(a->c1Ptr_);                  // a(c1Ptr_ = null), s(c1Ptr_ = null)
N n(a);                          // a(c1Ptr_ = null), s(c1Ptr_ = null), n(a_ = a)
                                 // [n.a_ points to a]

在这个初始指令块之后:

  • as 的共享指针成员 c1Ptr_ 的值为 nullptr。
  • n 的共享指针成员 a_ 指向对象 a.
s.c1Ptr_ = std::make_shared<C1>(12);  // (1) a(c1Ptr_ = null), s(c1Ptr_->x_ = 12 ), n(a_ = a) 
                                      //     [and you modify s]
if (n.a_->c1Ptr_) {
    std::cout << "c1Ptr is set for N\n\n";
}
else {
    std::cout << "c1Ptr is NOT set for N\n\n";  // (1)
}

此处:

  • 你只是修改了s.c1Ptr_,但这并不影响a,最终,n
  • s.c1Ptr_ 最初设置为指向与 a.c1Ptr_ 相同的 C1 对象(实际上是 nullptr);现在你只是让它指向别的东西。
a->c1Ptr_ = std::make_shared<C1>(15);  // (2) a(c1Ptr_->x_ = 15 ), s(c1Ptr_->x_ = 12 ), n(a_ = a)
                                       //     [and you modify a]
if (n.a_->c1Ptr_) {
    std::cout << "c1Ptr is set for N\n\n";  // (2)
}
else {
    std::cout << "c1Ptr is NOT set for N\n\n";
}

如果您改为 a->c1Ptr_ 会发生什么?由于 n->a_ 指向 a 而我们正在修改 a,因此 n->a_->c1Ptr_ 也被设置。

[Demo]