Writing a vector class c++

So I'm trying to write a vector class which can take objects without a default constructor. To do so I'm using an array of raw pointers. Thing is, when I'm instantiating a new vector, let's call it 2, based upon a previous vector, let's call it 1-- it points to the underlying address of said previous object, 1. So when I insert a new value into 1, 2 is updated as well.

#ifndef MYVECTOR_MYVECTOR_H
#define MYVECTOR_MYVECTOR_H

#include <sstream>
#include <stdexcept>
#include <memory>
#include <vector>
#include <ostream>

template<typename T>
class MyVector;

template<typename T>
std::ostream& operator<<(std::ostream& out, const MyVector<T>& myVec){
  out << "{";
  for(int i = 0; i < myVec.numElem; i++){
    out << &myVec.elements[i] << " ";
  }
  out << "}";
  return out;
}


template<typename T>
class MyVector{
  public:
      int numElem;
      int capacity;
      T** elements;

      MyVector(const unsigned int& numElements, const T& value) : numElem(numElements), capacity(numElements * 2){
          elements = new T*[capacity];
          for(int i = 0; i < numElem; i++){
              elements[i] = new T(value);
          }
      }

      template<typename U>
      MyVector(const std::vector<U>& values): numElem(values.size()), capacity(values.size() * 2){
        elements = new T*[capacity];
        for(int i = 0; i < numElem; i++){
            elements[i] = new T(values[i]);
        }
      }

    void insert(const unsigned& pos, const T& value){
        elements[numElem] = new T(*elements[numElem - 1]);
        numElem++;

        for(unsigned int i = numElem - 1; i > pos; i--){
            elements[i] = elements[i - 1];
        }
        elements[pos] = new T(value);
    }
};

#endif

Per comment #1:

class NoDefault {
 public:
  NoDefault(const int& value) : value(value) {}

  int value;
};

std::ostream& operator<<(std::ostream& out, const NoDefault& noDefault) {
  out << noDefault.value;
  return out;
}

int main() {
  MyVector<NoDefault> noDefaultVec(std::vector<NoDefault>{7,8,9,10,11});
  MyVector<MyVector<NoDefault>> vecvec(2, noDefaultVec);

  std::cout << "noDefaultVec = " << noDefaultVec << std::endl;
  std::cout << "vecvec = " << vecvec << std::endl;

  noDefaultVec.insert(3, 99);
  vecvec.insert(1, noDefaultVec);

  std::cout << "noDefaultVec = " << noDefaultVec << std::endl;
  std::cout << "vecvec = " << vecvec << std::endl;

  return 0;
}

Upvotes: 0

Views: 143

Answers (1)

Rozek
Rozek

Reputation: 53

You perform a shallow copy instead of a deep copy.

A shallow copy of your vector creates a new collection which shares elements with an old one. What follows, any change made to the original object will cause a change in a new one. What you need in that case is a deep copy, which duplicates every element from the source to the destination. After performing such a copy you are left with two vectors with seperate set of data.

Providing a copy constructor for your class solves the problem, but you should also remember about implementing destructor and assignment operator, basing on The Rule Of Three. You can also consider adding move constructor and move assignment operator (or one assignment operator following copy-and-swap idiom).

Upvotes: 1

Related Questions