Skip to content

Instantly share code, notes, and snippets.

@advnpzn
Last active June 13, 2025 18:31
Show Gist options
  • Save advnpzn/f265a4f89270e2da29d1d5ef556b2533 to your computer and use it in GitHub Desktop.
Save advnpzn/f265a4f89270e2da29d1d5ef556b2533 to your computer and use it in GitHub Desktop.
A basic non-thread safe implementation of vector (dynamic array) data structure in C++
#include <algorithm>
#include <cstddef>
#include <initializer_list>
#include <iostream>
#include <memory>
#include <stdexcept>
template <typename T> class Vector {
private:
T *data_ = nullptr;
size_t size_ = 0;
size_t capacity_ = 0;
public:
Vector() = default;
explicit Vector(const size_t &count)
: data_(new T[count]), size_(count), capacity_(count) {}
Vector(size_t count, const T &value) : Vector(count) {
std::fill_n(data_, size_, value);
}
Vector(std::initializer_list<T> init) : Vector(init.size()) {
std::copy(init.begin(), init.end(), data_);
}
~Vector() {
std::destroy(data_, data_ + size_);
delete[] data_;
}
Vector(const Vector &other) : Vector(other.size_) {
std::copy(other.data_, other.data_ + other.size_, data_);
}
Vector(Vector &&other) noexcept
: data_(other.data_), size_(other.size_), capacity_(other.capacity_) {
other.data_ = nullptr;
other.size_ = 0;
other.capacity_ = 0;
}
Vector &operator=(const Vector &other) {
if (this != &other) {
Vector temp(other);
swap(other);
}
return *this;
}
Vector &operator=(Vector &&other) noexcept {
if (this != &other) {
delete[] data_;
data_ = other.data_;
size_ = other.size_;
capacity_ = other.capacity_;
other.data_ = nullptr;
other.size_ = 0;
other.capacity_ = 0;
}
return *this;
}
T &operator[](const size_t &pos) {
if (pos >= size_) {
throw std::out_of_range("Index out of range");
}
return data_[pos];
}
T &at(const size_t &pos) {
if (pos >= size_) {
throw std::out_of_range("Index out of range");
}
return data_[pos];
}
size_t size() const noexcept { return size_; }
size_t capacity() const noexcept { return capacity_; }
bool empty() const noexcept { return size_ == 0; }
T &front() {
if (empty()) {
throw std::out_of_range("Vector is empty");
}
return data_[0];
}
T &back() {
if (empty()) {
throw std::out_of_range("Vector is empty");
}
return data_[size_ - 1];
}
T *data() noexcept { return data_; }
void clear() noexcept {
std::destroy(data_, data_ + size_);
size_ = 0;
}
void push_back(const T &value) {
if (size_ == capacity_) {
reserve(capacity_ ? capacity_ * 2 : 1);
}
data_[size_] = value;
++size_;
}
void push_back(T &&value) {
if (size_ == capacity_) {
reserve(capacity_ ? capacity_ * 2 : 1);
}
data_[size_] = std::move(value);
++size_;
}
void shrink_to_fit() {
if (size_ < capacity_) {
Vector temp(*this);
swap(temp);
}
}
template <typename... Args> void emplace_back(Args &&...args) {
if (size_ == capacity_) {
reserve(capacity_ ? capacity_ * 2 : 1);
}
new (&data_[size_]) T(std::forward<Args>(args)...);
++size_;
}
void pop_back() noexcept(std::is_nothrow_destructible_v<T>) {
if (empty()) {
throw std::out_of_range("Vector is empty");
}
std::destroy_at(std::addressof(data_[size_ - 1]));
--size_;
}
void resize(const size_t &new_size) {
if (new_size < size_) {
std::destroy(data_ + new_size, data_ + size_);
size_ = new_size;
} else if (new_size > size_) {
reserve(new_size);
std::uninitialized_value_construct(data_ + size_, data_ + new_size);
size_ = new_size;
}
}
void resize(const size_t &new_size, const T &value) {
if (new_size < size_) {
std::destroy(data_ + new_size, data_ + size_);
size_ = new_size;
} else if (new_size > size_) {
reserve(new_size);
std::uninitialized_fill(data_ + size_, data_ + new_size, value);
size_ = new_size;
}
}
void swap(Vector &other) noexcept {
std::swap(data_, other.data_);
std::swap(size_, other.size_);
std::swap(capacity_, other.capacity_);
}
void reserve(const size_t &new_capacity) {
if (new_capacity > capacity_) {
T *new_data = new T[new_capacity];
std::uninitialized_move(data_, data_ + size_, new_data);
std::destroy(data_, data_ + size_);
delete[] data_;
data_ = new_data;
capacity_ = new_capacity;
}
}
T *begin() noexcept { return data_; }
T *end() noexcept { return data_ + size_; }
};
int main() {
Vector<int> vec = {1, 2, 3, 4, 5};
vec.push_back(6);
vec.emplace_back(7);
vec.resize(10, 0);
for (const auto &item : vec) {
std::cout << item << " ";
}
std::cout << std::endl;
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment