通过C ++中的共享对象访问成员变量的安全方法是什么?
在下面的代码中,我创建了一个共享变量,然后是一个指向它的成员变量的指针。但是,use_count保持不变,当我重置共享变量时,原始变量被重置,但不是指向成员的指针。
换句话说,我可以通过使用b来介绍一些错误。它指向的对象不再存在。
#include <iostream>
#include <memory>
using namespace std;
struct A
{
int y;
A(int x)
{
y = x;
}
};
int main()
{
auto a = make_shared<A>(1);
cout << "a count: " << a.use_count() << endl; //prints a count: 1
auto b = a->y;
cout << "a count: " << a.use_count() << endl; //still prints a count: 1
a.reset();
cout << "a value: " << a << endl; //prints a value: 0
cout << "b value: " << b << endl; //prints b value: 1
return 0;
}
答案 0 :(得分:6)
auto b = a->y;
这将复制 y
的值,因此它不是指向y
的指针,它只是一个副本。
答案 1 :(得分:2)
auto a = make_shared<A>(1);
auto b = std::shared_ptr<int>(a, &a->y);
b是指向y的共享指针,可以执行您想要的操作。
这被称为共享ptr的“别名构造函数”。它的目的正是为了这个目的;将共享指针放入更大的共享ptr的一部分。
你可以将它用于许多疯狂和奇特的东西。使用它时要小心,因为你可以得到奇怪的状态,比如空的非空共享ptrs和非空的空共享ptrs。但是如果你像上面那样“正常”使用它,那就可以了。
你做了什么
auto a = make_shared<A>(1);
auto b = a->y;
只需将y
复制到b
,不会涉及任何指针。
答案 2 :(得分:1)
通过C ++中的共享对象访问成员变量的安全方法是什么?
你已经在做了。您展示的代码是安全的。
不,你不是。在下面的代码中,我创建了一个共享变量,然后是一个指向它的成员变量的指针。
A::y
是int
。在auto b = a->y;
语句中,auto
推断为int
,而不是int&
或int*
。因此,您要创建一个新的int
,其值为y
的副本。没有指向y
的指针。
如果你想要这样的东西,你需要使用其中之一:
auto &b = a->y;
...
cout << "b value: " << b << endl;
auto *b = &(a->y); // or just: auto b = ...
...
cout << "b value: " << *b << endl;
但是,use_count保持不变
更正,因为您没有将a
分配给另一个shared_ptr<A>
实例。这就是use_count
表示的内容 - 在内存中共享同一对象的shared_ptr
个对象的数量。
当我重置共享变量时,原始变量被重置但不是指向成员的指针。
当然,因为b
独立于a
,并且不是指向与a
相关的任何内容的指针。
换句话说,我可以通过使用b。
来介绍一些错误
不,因为b
未与a
相关联,因此重置a
对b
无效。
现在,如果你确实设法完成了你的要求(让b
成为y
的指针),你有责任确保A
对象{ {1}}已在内存中保持有效状态,直到您使用y
完成为止,否则解除引用b
将是未定义的行为。 STL不会让你在背后做一些愚蠢的事情,比如在对象被摧毁后通过原始指针访问b
对象的成员。
答案 3 :(得分:0)
故事的寓意是不要在参考之前分发对可能死亡的物品的引用。设计每个对象的生命周期。一种解决方案可能是复制params[:item_id]
以确保引用始终指向对象,当您不需要该对象仍然有效时,另一个解决方案可能是传递std::shared_ptr
。你需要知道,所以你不要试图使用它。只有在知道时,才会传出指针和引用。