我有一些代码添加到std::vector
and a std::map
创建对象后。
v.push_back(object); // std::vector
m[object->id] = object; // std::map
我想让这个有一个强有力的例外保证。通常,为了使此类操作原子化,我将为每个容器实现一个交换方法,并调用所有可能抛出容器临时副本的函数:
vector temp_v(v);
map temp_map(m);
temp_v.push_back(object);
temp_m[object->id] = object;
// The swap operations are no-throw
swap(temp_v, v)
swap(temp_m, m)
然而,制作整个矢量和地图的临时副本似乎非常昂贵。有没有办法在不使用昂贵副本的情况下为该函数实现强大的异常保证?
一般案例
从技术上讲,只需要一份副本:
- 复制向量
- 更新副本
- 更新地图
- 交换副本和原始向量
另一种选择是捕获-回滚-然后重新抛出:
v.push_back(object);
try
{
m.insert(object->id, object); // Assuming it cannot be present yet
}
catch(..)
{
v.pop_back();
throw;
}
或者反过来。我选择这个订单是因为vector::pop_back()
保证不会失败。
UPDATE:如果 object->id 可能存在,请参阅灰熊的回答 https://stackoverflow.com/a/8857799/396551寻求解决方案。
指针的具体情况
但是,当您使用object->
,您可能正在存储指针。指针的复制构造函数不能抛出异常,我们可以利用这一事实来简化代码:
v.reserve(v.size() + 1);
m[object->id] = object; // can throw, but not during the assignment
v.push_back(object); // will not throw: capacity is available, copy constructor does not throw
如果您真的担心频繁调整大小:
if (v.capacity() == v.size()) v.resize(v.size()*2); // or any other growth strategy
m[object->id] = object;
v.push_back(object);
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)