指向std :: map中的值的指针

时间:2009-07-16 05:34:04

标签: c++ stl

我有一个std :: map,多个线程用它来存储数据。地图声明如下:

std::map<int, Call> calls;

从每个线程,我必须获取一个互斥锁,获取指向该属性的对象的指针或引用,然后释放互斥锁。之后我可以修改对象,因为每个对象只由一个线程使用。一旦线程死亡,地图中的相应对也将被删除。

我想知道实现这个的最佳方法。我在考虑两种方式:

1)我知道这个人看起来非常疯狂,但仍然是

std::map<int, Call> calls;
...

{
    mutex.lock();
    Call* callptr = &calls[id];
    mutex.unlock();

   // use callptr
}

或2)我觉得这个看起来更明智

std::map<int, std::auto_ptr<Call> > calls;

...

{
    mutex.lock();
    std::auto_ptr<Call> callptr = map[id];
    mutex.unlock();

    // use callptr

    mutex.lock();
    map[id] = callptr;
    mutex.unlock();
}

线程实际上是在不同的dll中创建的,我没有代码。我正在编写的这个dll由该dll导入并使用。所以它必须只用std :: map实现,但是有人可以告诉我其中一种方法是否正常,或者是否有办法使它更稳定。

由于

3 个答案:

答案 0 :(得分:5)

你应该使用迭代器:

mutex.lock();

std::map<int, Call>::iterator callptr = calls.find(id);
callptr->second.foo();
...

mutex.unlock();

带指针的第一个解决方案存在问题,因为地图中对象的生命周期是不确定的 - 当插入或删除元素时重新平衡树时,可能会移动它。

您的第二个解决方案根本不起作用,因为std::auto_ptr无法满足mapped_type std::map的要求 - 主要是因为它的复制构造函数和operator=不是实际上是复制。您可能不会收到编译器错误,但在运行时会出现非常奇怪的行为。

答案 1 :(得分:3)

根据我Thread Local storage,对你来说是最好的选择。

如果您需要特定于线程的数据,则可以使用线程本地存储,并完全不需要映射和互斥锁定。

答案 2 :(得分:2)

不要在STL容器中使用auto_ptr。别。实现者实际上需要尝试在那里使用编译错误。标准容器往往会复制周围的东西。这对auto_ptr来说是非常错误的。