c++ - 像 std::vector 这样的 vector 类的简单实现

标签 c++ vector stl

我正在实现一个像 std::vector 这样的简单 vector ,并且我编写了一些函数,而不用担心它提供了什么样的异常安全保证。我对c++的异常了解一点,但是我没有写异常安全代码的经验。 这是我的代码:

template <typename T>
class vector {
public:
   vector(int _DEFAULT_VECTOR_SIZE = 10) :
       size(0), array_(new T[_DEFAULT_VECTOR_SIZE]), capacity(_DEFAULT_VECTOR_SIZE)  {}
  void push_back(T& elem)
  {
    if (size == capacity)
    resize(2 * size);
    array_[size] = elem;
    size++;
  }

  void pop_back()
  {
     --size;
  }

  void resize(int size_)
  {
     if (size_ > capacity)
    {
      T* temp = new T[size_];
      memcpy(temp,array_,size*sizeof(T));
      swap(temp, array_);
      delete[] array_; 
      capacity = size_;
     }
  }

  private:
    T* array_; 
    int size;
    int capacity;
 };

所以我的问题是:我如何修改我的代码(函数),至少提供基本保证,或者一些编写异常安全代码以提供基本或强保证的技术? 谢谢

最佳答案

异常安全有两种主要形式:

  1. 如果发生异常,您的程序将以正常状态结束。哪个未指定。
  2. 如果发生异常,您的程序将以原始状态结束。

您面临的主要挑战是处理赋值和复制构造函数抛出的问题。正如评论已经指出的那样,您不应使用 memcpy 因为它无法调用复制构造函数。复制 std::string 也应该复制字符缓冲区,例如,字符串 vector 是您应该支持的完全正常的类型。

那么,让我们看看 vector 的复制构造函数。它将需要复制源 vector 的每个元素。而且每个单独的拷贝都可以扔。如果其中一个字符串太长以至于拷贝抛出 std::bad_alloc 怎么办?

现在,异常安全意味着您让程序处于正常状态,因此没有内存泄漏。您的 vector 的复制 ctor 失败,因此 dtor 不会运行。那么谁来清理 T* array 呢?这必须在您的复制 ctor 中完成。

当复制失败时,不会有新的vector,所以你就免费获得了第二种异常安全。 (“强异常安全”)。但是接下来让我们看一下赋值运算符,v2 = v1。您将覆盖一个旧 vector 。如果您先执行 .resize(0) 然后复制所有元素,您可能会在复制过程中遇到异常。你原来的 vector 内容没有了,新的内容不完整。不过,您还没有泄漏任何内存,也没有复制半个元素。

为了确保分配安全,有一个简单的技巧:首先将源 vector 复制到临时 vector 。如果失败,没问题(见上文)。我们还没有到达目的地。但如果赋值成功,我们将交换临时 vector 和目标 vector 的 array* 指针、sizecapacity。交换指针和交换整数是安全的(不能抛出)。最后,我们让临时 vector 超出范围,这会破坏不再需要的旧 vector 元素。

因此,通过对临时对象执行所有危险操作,我们确保任何异常都不会触及原始状态。

您需要检查所有方法以查看是否会出现这些问题,但模式通常是相似的。如果元素复制或元素分配抛出异常,请不要泄漏 array,请将该异常传播给调用者。

关于c++ - 像 std::vector 这样的 vector 类的简单实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28720595/

相关文章:

c++ - 为什么 va_start 会失败?

c++ - 备用http端口?

c++ - 如何将原始字节附加到 std::vector?

c++ - 在 C/C++ 中分解 UDP 传输中的 double

r - 向量元素的所有组合之间的乘积

c++ - 3D vector 的高效量级计算

c++ - 生成和复制 vector 的 STL 算法

c++ - 关于 std::less 行为的问题

c++ - 为什么无序关联容器不实现小于运算符?

c++ - 使用 STL 流时如何格式化我自己的对象?