gpt4 book ai didi

c++ - 添加到多个 std 容器时 C++ 中的异常安全

转载 作者:IT老高 更新时间:2023-10-28 23:17:08 25 4
gpt4 key购买 nike

我有一些代码在创建对象后添加到 std::vectorstd::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)

但是,制作整个 vector 和 map 的临时拷贝似乎非常昂贵。有没有办法在没有昂贵拷贝的情况下为此功能实现强大的异常保证?

最佳答案

一般情况

从技术上讲,只需要一份:

  1. 复制 vector
  2. 更新拷贝
  3. 更新 map
  4. 交换拷贝和原始 vector

另一个选项是 catch-roll-back-and-rethrow:

  v.push_back(object);
try
{
m.insert(object->id, object); // Assuming it cannot be present yet
}
catch(..)
{
v.pop_back();
throw;
}

或者反过来。我选择这个顺序是因为 vector::pop_back() 保证不会失败。

更新:如果可能存在 object->id,请参阅 Grizzly's answer寻求解决方案。


指针的具体情况

但是,当您使用 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);

关于c++ - 添加到多个 std 容器时 C++ 中的异常安全,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8857567/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com