指向shared_ptr的成员变量的指针

时间:2018-01-13 02:40:46

标签: c++ c++11 shared-ptr pointer-to-member

通过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;
}

4 个答案:

答案 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::yint。在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相关联,因此重置ab无效。

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

答案 3 :(得分:0)

故事的寓意是不要在参考之前分发对可能死亡的物品的引用。设计每个对象的生命周期。一种解决方案可能是复制params[:item_id]以确保引用始终指向对象,当您不需要该对象仍然有效时,另一个解决方案可能是传递std::shared_ptr。你需要知道,所以你不要试图使用它。只有在知道时,才会传出指针和引用。