通过引用获取std :: map中的对象是否安全?

时间:2010-12-29 15:58:41

标签: c++ reference map

我有这样的地图

map<int,object> objmap;
object& obj = objmap.find(num)->second;
object& obj2 = objmap[num];

我在对象中所做的任何更改都必须反映在地图上。类似的事情不能在矢量中完成,因为它在需要更多空间时改变对象的位置。在std :: map中执行它是否安全?这是可取的吗? 第二个版本给出错误,因为我的对象没有空构造函数。如果我声明一个空构造函数什么也不做,这两行会以同样的方式工作吗?

5 个答案:

答案 0 :(得分:22)

只要有问题的对象没有从地图中移除,那么是的,它是安全的。一旦插入到地图中,即使添加或删除了其他元素,也不会移动对象。

object& obj = objmap.find(num)->second;

除非您确定地图中确实存在键num的元素,否则这是有潜在危险的。如果您不确定,可以使用insert的重载返回iteratorbool,指示是否插入了新元素或者是否已存在具有给定键的元素在地图上。

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()。

与任何集合/缓存等一样,如果在多线程应用程序中完成,则必须注意线程安全问题。

我不确定你想知道的是你是否可以将引用存储在某处(或指向它的指针),并期望它在以后将其他项添加到地图时有效,是的,它会是。

相关问题