【问题标题】:Accessing member variables through static pointer to instance通过指向实例的静态指针访问成员变量
【发布时间】:2014-04-23 18:01:28
【问题描述】:

我有一个类,其中包含指向该类所有实例的静态指针向量。当我通过静态 getter 方法访问成员变量时,有时会得到错误的结果。

代码:
hpp 文件:

class ObjectID {
    public:
        ObjectID();
        float getShininess() const { return m_shininess; }
        static const std::shared_ptr<ObjectID> getID(unsigned long);
    private:
        float m_shininess;
        static std::vector<std::shared_ptr<ObjectID>> s_ids;
}

cpp 文件:

static std::mutex s_mutex;
std::vector<std::shared_ptr<ObjectID>> ObjectID::s_ids = {};

const std::shared_ptr<ObjectID> ObjectID::getID(unsigned long id) {
    std::lock_guard<std::mutex> lock(s_mutex);
    std::shared_ptr<ObjectID> ptr = s_ids.at(id - 1);
    return ptr;
}

ObjectID::ObjectID()
  : m_shininess(50.f)
{
    std::lock_guard<std::mutex> lock(s_mutex);
    s_ids.emplace_back(this);
}

我怀疑这与我使用两个线程的事实有关。但是添加互斥锁并没有改变任何东西。

为了澄清,一个线程创建 ObjectID,另一个线程调用

ObjectID::getID(id)->getShininess();

我并不总是得到 50,有时我得到 1,而且我从不改变 m_shininess。 有什么想法吗?

编辑

ObjectID 是在另一个类中创建的,该类具有 ObjectID 的向量。

m_objects.emplace_back();

【问题讨论】:

  • 你怎么知道哪些 id 是有效的?
  • 你怎么知道s_ids.emplace_back(this); 中的this 甚至是动态分配的?
  • @nosid:在 cpp 文件中,我将其添加到代码中。
  • @WhozCraig -- 确切地说,如果 ObjectID 是在堆栈上创建的,或者它是在构造函数外部创建并绑定到 shared_ptr 的,这可能会失败。
  • @gartenriese 类似于我可能会这样做,特别是隐藏构造函数。如果这是多线程的,你仍然需要在修改和查询期间保护s_ids,但模型是健全的。

标签: c++ multithreading static


【解决方案1】:

您的向量包含 shared_ptr,但您将指向 ObjectID (this) 的原始指针放入其中。由于 shared_ptrs 可以从编译的原始对象构建,但它可能没有按照您的意愿执行。特别是,如果 ObjectID 通过其他方式被破坏,您将在该向量中得到野指针。我不确定这是否是您的问题的原因,但至少是可疑的。

我不知道您的确切要求,但也许这样的事情会有所帮助?

class ObjectID
{
public:
   static std::shared_ptr<ObjectID> Create()
   {
       auto created = std::make_shared<ObjectID>();
       s_ids.push_back(created);
       return created;
   }  

private:
   ObjectID()
   {
      // as before
   }
};

【讨论】:

  • 好吧,我想我需要一个更好的解决方案。但是,我没有销毁任何 ObjectID,至少据我所知没有!
  • 同意。如果将 ObjectID 对象分配给构造函数外部的 shared_ptr,这也可能是一个问题。它们将具有单独的所有权计数,一旦两者之一变为零,即使在其他地方有对原始指针的引用,它也会炸毁该对象。如果您在创建 ObjectID 值的地方发布更多代码,我们可能会提供更多帮助。
  • @gartenriese:他们是如何保持活力的?它们最初是如何构建的?
  • @mwigdahl:我添加了有关如何创建 ObjectID 的信息。
  • 如果你想让静态向量保持活动状态,你可以用创建 shared_ptr 的静态工厂函数替换公共 ObjectID 构造函数,将 shared_ptr 推送到向量上,然后返回它(我编辑了我的答案以显示这一点)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多