vector的简单实现

需要提供的接口:

1、构造、拷贝构造、移动构造

2、operator[]、=(copy and move)

3、resize reserve push_back emplace_back pop_back swap

#include 
#include 
#include 
template<typename T>

class Vector {
public:
    Vector() : size_(0), capacity_(0), data_(nullptr) {}
    // copy construct
    Vector(const Vector& other) : size_(other.size_), capacity_(other.capacity_), data_(new T[capacity_]) {
        for (size_t i = 0; i < size_; i++) {
            data_[i] = other.data_[i];
        }
    }
    // move construct
    Vector(Vector&& other) noexcept : size_(other.size_), capacity_(other.capacity_), data_(other.data_) {
        other.size_ = 0;
        other.capacity_ = 0;
        other.data_ = nullptr;
    }
    // copy =
    Vector& operator=(const Vector& other) {
        if (this != &other) {
            delete[] data_;
            size_ = other.size_;
            capacity_ = other.capacity_;
            data_ = new T[capacity_];
            for (size_t i = 0; i < size_; i++) {
                data_[i] = other.data_[i];
            }
        }
        return *this;
    }
    // move =
    Vector& operator=(Vector&& other) noexcept {
        if (this != &other) {
            delete[] data_;
            size_ = other.size_;
            capacity_ = other.capacity_;
            data_ = other.data_;
            other.size_ = 0;
            other.capacity_ = 0;
            other.data_ = nullptr;
        }
        return *this;
    }

    ~Vector() {
        if (data_ != nullptr) {
            delete[] data_;
        }
    }

    // 这里使用万能引用去捕获左值 右值
    template<typename U>
    void push_back(U&& value) {
        if (size_ == capacity_) {
            reserve(capacity_ == 0 ? 1 : capacity_ * 2);
        }
        data_[size_++] = std::forward<U>(value);
    }

    void pop_back() {
        if (size_ == 0) {
            throw std::out_of_range("Vector is empty");
        }
        --size_;
    }

    template<typename ... Args>
    void emplace_back(Args&& ... args) {
        if (size_ == capacity_) {
            reserve(capacity_ == 0 ? 1 : capacity_ * 2);
        }
        new (&data_[size_++]) T(std::forward<Args>(args)...);
    }

    T& operator[](size_t index) {
        if (index >= size_) {
            throw std::out_of_range("Index out of range");
        }
        return data_[index];
    }

    const T& operator[](size_t index) const {
        if (index >= size_) {
            throw std::out_of_range("Index out of range");
        }
        return data_[index];
    }

    size_t size() const {
        return size_;
    }

    size_t capacity() const {
        return capacity_;
    }

    bool empty() const {
        return size_ == 0;
    }

    void clear() {
        size_ = 0;
    }

    void resize(size_t new_size) {
        if (new_size > size_) {
            reserve(new_size);
            for (size_t i = size_; i < new_size; i++) {
                new (&data_[i]) T();
            }
        } else {    // 否则析构掉多余的元素
            for (size_t i = new_size; i < size_; i++) {
                data_[i].~T();
            }
        }
        size_ = new_size;
    }

    void reserve(size_t new_capacity) {
        if (new_capacity > capacity_) {
            T* new_data = new T[new_capacity];
            for(size_t i = 0; i < size_; i++) {
                new_data[i] = data_[i];
            }
            delete[] data_;
            data_ = new_data;
            capacity_ = new_capacity;
        }
    }

    void swap(Vector& other) noexcept {
        std::swap(size_, other.size_);
        std::swap(capacity_, other.capacity_);
        std::swap(data_, other.data_);
    }

private:
    size_t size_;
    size_t capacity_;
    T* data_;
};

int main() {
    Vector<int> v;
    v.push_back(1);
    v.push_back(2);
    v.push_back(3);
    std::cout << "v: ";
    for (size_t i = 0; i < v.size(); ++i) {
        std::cout << v[i] << " ";
    }
    std::cout << std::endl;
    Vector<int> v2(v);
    std::cout << "v2: ";
    for (size_t i = 0; i < v2.size(); ++i) {
        std::cout << v2[i] << " ";
    }
    std::cout << std::endl;

    Vector<int> v3(std::move(v));
    std::cout << "v3: ";
    for (size_t i = 0; i < v3.size(); ++i) {
        std::cout << v3[i] << " ";
    }
    std::cout << std::endl;

    Vector<int> v4;
    v4 = v2;
    std::cout << "v4: ";
    for (size_t i = 0; i < v4.size(); ++i) {
        std::cout << v4[i] << " ";
    }
    std::cout << std::endl;

    Vector<int> v5;
    v5 = std::move(v3);
    std::cout << "v5: ";
    for (size_t i = 0; i < v5.size(); ++i) {
        std::cout << v5[i] << " ";
    }
    std::cout << std::endl;

    v5.resize(5);
    std::cout << "v5: ";
    for (size_t i = 0; i < v5.size(); ++i) {
        std::cout << v5[i] << " ";
    }
    std::cout << std::endl;

    v5.resize(3);
    std::cout << "v5: ";
    for (size_t i = 0; i < v5.size(); ++i) {
        std::cout << v5[i] << " ";
    }
    std::cout << std::endl;

    v5.clear();
    std::cout << "v5: ";
    for (size_t i = 0; i < v5.size(); ++i) {
        std::cout << v5[i] << " ";
    }
    std::cout << std::endl;

    return 0;
}

打印的结果如下:

v: 1 2 3
v2: 1 2 3
v3: 1 2 3
v4: 1 2 3
v5: 1 2 3
v5: 1 2 3 0 0
v5: 1 2 3
v5:

emplace_back函数可以用于在vector的末尾直接构造一个元素,而不需要先创建一个临时对象再将其拷贝或移动到vector中。

这个实现使用了 C++11 中的变长模板参数和完美转发,可以接受任意数量和类型的参数,并将它们转发给 T 类型的构造函数。

在实现中,我们首先检查 vector 是否已经满了,如果是,则调用 reserve 函数来扩展 vector 的容量。然后,我们使用 placement newvector 的末尾直接构造一个元素,而不需要先创建一个临时对象再将其拷贝或移动到 vector 中。最后,我们将 vector 的大小加一。

需要注意的是,使用 placement new 构造对象时,需要将对象的地址作为第一个参数传递给 new 运算符,这样才能在指定的地址上构造对象

在这个实现中,我们使用了完美转发来将 push_back 函数优化成一个函数。我们还实现了 resize 函数来调整 vector 的大小,并使用了移动构造和拷贝构造函数来实现对象的拷贝和移动。我们还实现了 swap 函数来交换两个 vector 对象的内容。 在 main 函数中,我们创建了几个 vector 对象,并测试了它们的各种函数。我们可以看到,这个 vector 类的实现可以正确地处理对象的拷贝和移动,并且可以动态调整 vector 的大小。

你可能感兴趣的:(#,C++,挖坑与填坑,面经,c++,算法,开发语言)