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_ptr
s.
的值
您可以通过绘制对象 a
、s
和 n
及其内容以及它们的内容所指向的内容来尝试自己解决这个问题:
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]
在这个初始指令块之后:
a
和 s
的共享指针成员 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_
也被设置。
我有一个结构 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_ptr
s.
您可以通过绘制对象 a
、s
和 n
及其内容以及它们的内容所指向的内容来尝试自己解决这个问题:
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]
在这个初始指令块之后:
a
和s
的共享指针成员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_
也被设置。