【发布时间】:2015-07-13 08:35:16
【问题描述】:
考虑下面的简化代码,Cache::operator[] 的调用者保证会收到映射值的副本?
#include <string>
#include <map>
#include <mutex>
#include <iostream>
class Cache {
public:
std::string operator[] (int k) {
std::lock_guard<std::mutex> lock(m_mutex);
if (! m_map.count(k)) m_map[k] = "Hello world";
return m_map[k];
}
private:
std::mutex m_mutex;
std::map<int, std::string> m_map;
};
int main (int argc, char *argv[]) {
Cache c;
auto v = c[42];
std::cout << v << std::endl;
return 0;
}
正如我看到的那样,我的意图是并发,并且在互斥锁释放后,映射值的继续存在并不能保证。
std::map<>::operator[] 返回引用 std::string&。我的理解是复制构造会产生一个无名的临时性,然后可能会受到 RVO 的约束。
复制省略何时会发生,这是否会导致不同的线程返回相同的对象而不是它们自己的副本?如果可以,如何避免?
实际代码涉及数据库查找填充缓存,其中映射键是表主键,映射值是从行字段构造的对象。
【问题讨论】:
-
@inf 谢谢。因此,如果我理解正确更改
Cache::operator[] (int)以返回引用 (std::string&) 会破坏所需的并发性? -
是的,因为这样用户可以通过引用而不是副本直接访问。
标签: c++ concurrency stl thread-safety