繁体   English   中英

向量类的简单实现,如std :: vector

[英]Simple implementation of vector class like std::vector

我正在实现一个简单的向量,例如std :: 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还应该复制字符缓冲区,字符串向量是您应该支持的完全正常的类型。

因此,让我们看一下向量的副本构造函数。 它将需要复制源向量的每个元素。 每个副本都可以抛出。 如果其中一个字符串太长而导致副本抛出std::bad_alloc怎么办?

现在,异常安全性意味着您将程序保持在理智状态,因此不会发生内存泄漏。 向量的复制ctor失败,因此dtor无法运行。 谁清理T* array呢? 这必须在您的复制控制器中完成。

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

为了使分配安全,有一个简单的技巧:首先将源向量复制到临时向量。 如果失败,则没有问题(请参见上文)。 我们尚未触及目的地。 但是,如果分配成功,我们将交换array*指针,临时矢量和目标矢量的sizecapacity 交换指针和交换int是安全的(不能抛出)。 最后,我们让临时向量超出范围,这会破坏不再需要的旧向量元素。

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM