英文:
Why is the address of an object stored in shared_ptr different than the original address?
问题
我正在学习shared_ptr的用法。
我原以为shared_ptr会存储原始对象A。
这是演示代码https://godbolt.org/z/nqrMhcz95。我注意到a、b.a_和sa的地址是不同的。
结构体 A {
int getValue() {
return a;
}
int a;
};
结构体 A1 {
int a;
};
结构体 B {
B(A& a) : a_(std::make_shared(a)), a1_(std::make_shared
A& getA() { return *a_; }
std::shared_ptr<A> a_;
std::shared_ptr<A1> a1_;
};
int main() {
A a;
B b{a};
std::shared_ptr sa = std::make_shared(a);
cout << &a << '\n';
cout << &(*b.a_) << '\n';
cout << &(*sa) << '\n';
b.getA().a = 4;
cout << a.getValue() << '\n'; // 期望修改的值反映在原始对象a中
}
我是否误解了shared_ptr的行为?
我如何修改存储在shared_ptr中的对象的值?
英文:
I'm learning the usage of shared_ptr.
I was expecting the shared_ptr stores the original object A.
Here is the demo code https://godbolt.org/z/nqrMhcz95. I've noticed the address of a, b.a_ and sa are different.
struct A {
int getValue() {
return a;
}
int a;
};
struct A1 {
int a;
};
struct B {
B(A& a) : a_(std::make_shared<A>(a)), a1_(std::make_shared<A1>(A1())){};
A& getA() { return *a_; }
std::shared_ptr<A> a_;
std::shared_ptr<A1> a1_;
};
int main() {
A a;
B b{a};
std::shared_ptr<A> sa = std::make_shared<A>(a);
cout << &a << '\n';
cout << &(*b.a_) << '\n';
cout << &(*sa) << '\n';
b.getA().a = 4;
cout << a.getValue() << '\n'; // expecting the modified value reflect in the original object a
}
Did I misunderstand the behaviour of shared_ptr?
How can I modify the value of an object stored in a shared_ptr?
答案1
得分: 3
在以下代码中:
A a;
std::shared_ptr<A> sa = std::make_shared<A>(a);
a
和 sa
引用不同的对象。make_shared
总是会创建一个新的对象,然后将 a
传递给新分配的 A
实例的拷贝构造函数。
要使两个变量都指向同一个对象,你需要将它们都声明为 shared_ptr
,如下所示:
std::shared_ptr<A> a = std::make_shared<A>();
std::shared_ptr<A> sa = a;
对于 B
,同样的规则适用,如果你希望其成员指向相同的对象,传递给构造函数的参数需要是一个 shared pointer。
请注意,如果你不希望所有这些对象共享对 A
的所有权,你可以使用引用来实现相同的效果,但你必须确保原始对象的生存期超过了所有引用。
不要尝试将现有对象的指针传递给 shared_ptr
构造函数:
A a;
std::shared_ptr<A> sa{&a};
这起初似乎可以工作,a
和 sa
将引用相同的对象,但当销毁 sa
时,它将尝试删除 a
,这是未定义的行为,因为 a
没有使用 new
进行分配。
英文:
In
A a;
std::shared_ptr<A> sa = std::make_shared<A>(a);
a
and sa
refer to different objects. make_shared
will always create a new object, a
is then passed to the copy constructor of the newly allocated instance of A
.
To have two variables that both point to the same object you'll need both of them to be shared_ptr
s:
std::shared_ptr<A> a = std::make_shared<A>();
std::shared_ptr<A> sa = a;
The same applies in B
, if you want its member to point to the same object the parameters passed to the constructor needs to be a shared pointer.
Note that if you don't want all of these objects to share ownership of A
you could achieve the same with references but you'd then have to make sure the original object outlives all the references.
Don't be tempted to pass a pointer to an existing object into the shared_ptr
constructor:
A a;
std::shared_ptr<A> sa{&a};
This will initially appear to work and a
and sa
will refer to the same object but when sa
is destroyed it will attempt to delete a
which is undefined behaviour as a
wasn't allocated with new
.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论