简体   繁体   中英

Simple implementation of vector class like std::vector

I'm implementing a simple vector like std::vector, and I wrote some functions , without worrying what kind of exception safe guarantee it gives. I know a little about exceptions of c++, but i have not experienced writing exception safe codes. Here is my code :

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;
 };

So my question is: How can I modify my code(functions) , that would give at least basic guarantee , or some technique of writing exception safe code for basic or strong guarantee ? Thanks

Exception-safety comes in two major flavours:

  1. If an exception happens, your program ends in a sane state. Which one is unspecified.
  2. If an exception happens, your program ends in the original state.

The main challenge for you will be to deal with assignment and copy constructors throwing. As the comments already note, you shouldn't use memcpy because that fails to call copy constructors. Copying a std::string should also copy the character buffer, for instance, and a vector of strings is a perfectly normal type which you should support.

So, let's look at your vector's copy constructor. It will need to copy every element of the source vector. And each individual copy can throw. What if one of the strings is so long that a copy throws std::bad_alloc ?

Now, exception safety means that you leave the program in a sane state, so no memory leaks. Your vector's copy ctor failed, so the dtor won't run. Who cleans up T* array then? This must be done in your copy ctor.

When the copy fails, there won't be a new vector, so you get the second type of exception safety for free. ("strong exception safety"). But let's look at the assignment operator next, v2 = v1 . There's an old vector that you will overwrite. If you first do a .resize(0) and then copy over all elements, you may encounter an exception halfway through the copy. Your original vector content is gone, and the new content is incomplete. Still, you haven't leaked any memory yet nor have you copied half an element.

To make the assignment safe, there's a simple trick: first copy the source vector to a temporary vector. If this fails, no problem (see above). We didn't touch the destination yet. But if the assignment succeeds, we swap the array* pointers, size and capacity of the temporary and the destination vectors. Swapping pointers and swapping ints is safe (can't throw). Finally, we let the temporary vector go out of scope which destroys the old vector elements that are no longer needed.

So, by doing all the dangerous operations on temporaries, we ensure that any exception doesn't touch the original state.

You'll need to check all your methods to see if these problems can occur, but the pattern is usually similar. Don't leak array if an element copy or element assignment throws, do propagate that exception to your caller.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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