Search code examples
c++new-operatorundefined-behaviordelete-operatorassignment-operator

Self-made ugly vector


I've got some training example of selt-made vector, it's not template for simplicity:

class UglyStringsVector {
public:
  UglyStringsVector() = default;
  explicit UglyStringsVector(size_t size);
  UglyStringsVector(const UglyStringsVector&);
  ~UglyStringsVector();

  std::string &operator[](size_t index);

  std::string *begin();
  std::string *end();

  const std::string *begin() const;
  const std::string *end() const;

  size_t Size() const;
  size_t Capacity() const;

  void PushBack(std::string value);
  void operator=(const UglyStringsVector &other);

private:
  std::string *data = nullptr;
  size_t size = 0;
  size_t capacity = 0;

  void ExpandIfNeeded();
};

Assignment operator is not implemented correctly:

UglyStringsVector& UglyStringsVector::operator=(const UglyStringsVector &other) {
  delete[] data;
  data = new std::string[other.capacity];
  size = other.size;
  capacity = other.capacity;
  copy(other.begin(), other.end(), begin());
  return *this;
}

As we see here, when this == &other (I don't check this condition on purpose of question), it deletes its own memory (of course this is wrong), and then reallocates new strings on the same place (data = new std::string[other.capacity];), strings are not uninitialized, because default constructor was called during operator new[], and then copy strings to themselves (copy(other.begin(), other.end(), begin());).

Lets imagine than losing memory is not problem :-) Something whispers to me that copying memory to itself is undefined behavior, but I'm not sure. The question: is there any undefined behavior?


Solution

  • Assuming that data is a valid pointer or nullptr, then actually there's no UB at all.

    With new std::string[other.capacity] you create an "array" of default-initialized std::string objects. A default-initialized (default-constructed basically) std::string is a valid but empty string.

    You then copy this array of empty strings to itself, which is fine.


    Regarding the self-copying, it's similar to

    int a = 0;
    a = a;
    

    which is weird but fine.