我有这样的地图
map<int,object> objmap;
object& obj = objmap.find(num)->second;
object& obj2 = objmap[num];
我在对象中所做的任何更改都必须反映在地图上。类似的事情不能在矢量中完成,因为它在需要更多空间时改变对象的位置。在std :: map中执行它是否安全?这是可取的吗? 第二个版本给出错误,因为我的对象没有空构造函数。如果我声明一个空构造函数什么也不做,这两行会以同样的方式工作吗?
答案 0 :(得分:22)
只要有问题的对象没有从地图中移除,那么是的,它是安全的。一旦插入到地图中,即使添加或删除了其他元素,也不会移动对象。
object& obj = objmap.find(num)->second;
除非您确定地图中确实存在键num
的元素,否则这是有潜在危险的。如果您不确定,可以使用insert
的重载返回iterator
和bool
,指示是否插入了新元素或者是否已存在具有给定键的元素在地图上。
E.g。
object& obj = objmap.insert( std::make_pair(num, object(arg1, arg2, argN)) ).first->second;
答案 1 :(得分:11)
只要元素未从地图中删除,这是安全的。
但是,第二行不是完全安全:
object& obj = objmap.find(num)->second;
如果地图中没有包含密钥num
的元素,find
将返回objmap.end()
。在取消引用返回的迭代器之前,应该测试这种可能性:
const std::map<int, object>::iterator it = objmap.find(num);
if (it != objmap.end())
{
object& obj = it->second;
/* ... */
}
现在,如果目标不是找到而是真的要插入,那么调用operator[]
是可能的(尽管如你所知,它需要提供一个值无参数构造函数)。但你必须明白,这是两个截然不同的事情:
find
仅发现:如果未找到密钥,则不会插入任何内容并返回end
迭代器operator[]
总是返回对地图中值的引用:如果密钥缺失,则会发生插入(对于默认构造值:因此构造函数要求)答案 2 :(得分:4)
如果你的问题是std::map
是否在其变异函数中使其迭代器无效,那么答案是否定的。标准保证std::map
不会使其迭代器失效。
答案 3 :(得分:1)
如果要反映对地图中对象所做的更改,您可能希望更改地图以存储指向对象的指针而不是对象本身。只要您在对象无效的对象之间做任何操作,引用就可以工作。
例如,以下代码将使用引用中断:
object& obj = objmap.find(num)->second;
objmap.erase(objmap.find(num)); // should check for objmap.end() - left out for simplicity
obj.DoSomething(); // this object has been destroyed, so the reference is invalid
答案 4 :(得分:0)
执行您正在执行的操作是实现缓存的常用方法。
如果项目已经存在,则operator []返回该项目。如果不存在,它将使用默认构造函数创建一个“空白”,您可以将其写入以供以后使用。
当然,通常使用shared_ptr作为value_type,在创建时它将具有“空”值。在这种情况下,您需要通过引用获取shared_ptr,以便可以在其上调用reset()。
与任何集合/缓存等一样,如果在多线程应用程序中完成,则必须注意线程安全问题。
我不确定你想知道的是你是否可以将引用存储在某处(或指向它的指针),并期望它在以后将其他项添加到地图时有效,是的,它会是。