指向 shared_ptr 成员变量的指针

Pointer to member variable of shared_ptr

在 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;
}
auto b = a->y;

这将复制 y 的值,因此它不是指向y 的指针,它只是一个副本。

What is a safe way to accessing member variables through a shared object in C++?

你已经在做了。您显示的代码是安全的。

In the code below, I make a shared variable and then a pointer to a member variable of it.

不,你不知道。 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;

However, the use_count remains unchanged

正确,因为您没有将 a 分配给 shared_ptr<A> 的另一个实例。这就是 use_count 所代表的 - 在内存中共享同一对象的 shared_ptr 个对象的数量。

when I reset the shared variable the original variable is reset but not the pointer to member.

当然,因为 b 独立于 a 并且不是指向任何与 a 相关的指针。

In other words, I could introduce some bugs by using b.

没有,因为b没有链接到a,所以重置ab没有影响。

现在,如果您确实设法完成了您的要求(使 b 成为指向 y 的指针),您有责任确保 A 对象y 的访问在内存中保持有效,直到您使用 b 完成,否则取消引用 b 将是 未定义的行为 。 STL 不会让你免于在背后做一些愚蠢的事情,比如在对象被销毁后通过原始指针访问 A 对象的成员。

这个故事的寓意是不要分发对可能在引用之前死亡的对象的引用。设计时要考虑到每个物体的使用寿命。一种解决方案可能是复制 std::shared_ptr 以确保引用始终指向对象,另一种解决方案可能是在不需要对象仍然有效但需要时传递 std::weak_ptr知道所以你不要尝试使用它。仅当您知道对象将比它们长寿时才传递指针和引用。

auto a = make_shared<A>(1);
auto b = std::shared_ptr<int>(a, &a->y);

b 是指向 y 的共享指针,可以满足您的需求。

这就是共享指针的 "aliasing constructor"。它正是为此目的而设计的;将共享指针指向更大共享指针的一部分。

你可以用它来做很多疯狂和奇特的事情。使用它时要小心,因为您可能会遇到奇怪的状态,例如空非空共享指针和非空空共享指针。但是如果你像上面那样使用它"normally",它就可以正常工作。

你做了什么

auto a = make_shared<A>(1);
auto b = a->y;

简单地将y复制到b,不涉及指针。