(C++) 简单实现vector

前言

对于自己尝试写的一些模仿标准库等操作。永远不要觉得自己实现的有多nb,在各大编译器的标准库面前就是个弟弟。

因此别再觉得自己数据结构课上写的那些基础线性表操作有多熟料,只能说人外有人,山外有山。

对于实现一个vector的基本考虑

  • 数据类型的声明
  • 构造 constructor
  • 析构 destructor
  • 拷贝 移动 copy move
  • 迭代器 iterators
  • 存取器 accessor
  • 容量 capacity
  • 修改器 modifier
  • 尾部追加删除 do_back
  • 运算符重载
  • 等等等等

Code

本文参考 LH_Mouse 的简单vector的实现,作为笔记和交作业。

LH_Mouse 的基础版本

手写一个 std::vector 可以有多复杂?_哔哩哔哩_bilibili

这只是在短时间内能考虑到的简单版本~

#include <stddef.h>

#include <iostream>
#include <string>

namespace my {
    
    
template <class ValueT>
class vector {
    
    
public:
    using value_type = ValueT;
    using reference = ValueT&;
    using const_reference = const ValueT&;
    using iterator = ValueT*;
    using const_iterator = const ValueT*;
    using size_type = ::size_t;
    // 迭代器相减
    using difference_type = ::ptrdiff_t;

private:
    ValueT* m_data;
    ::size_t m_size;
    ::size_t m_capacity;

public:
    // 默认无参构造
    constexpr vector() noexcept : m_data(), m_size(), m_capacity() {
    
    
    }

    // 内存是vector自己管理的
    // 只想销毁对象
    ~vector() {
    
    
        this->clear();
        ::operator delete(this->m_data);
    }

    // 拷贝构造
    vector(const vector& rhs) {
    
    
        // 注意 operator new 会抛出异常
        this->m_data = static_cast<ValueT*>(
            ::operator new(rhs.m_capacity * sizeof(ValueT)));

        this->m_size = 0;
        this->m_capacity = rhs.m_capacity;
        try {
    
    
            for (::size_t k = 0; k < rhs->m_size; k += 1) {
    
    
                // placement new
                // new时考虑异常
                ::new (&this->m_data[k]) ValueT(rhs.m_data[k]);
                this->m_size += 1;
            }
        } catch (...) {
    
    
            for (::size_t k = 0; k < this->m_size; k += 1) {
    
    
                this->m_data[k].~ValueT();
            }
            ::operator delete(this->m_data);
            // 将异常重新抛出
            throw;
        }
    }

    // 移动构造
    vector(vector&& rhs) {
    
    
        this->m_data = rhs.m_data;
        this->m_size = rhs.m_size;
        this->m_capacity = rhs.m_capacity;

        rhs.m_data = nullptr;
        rhs.m_size = 0;
        rhs.m_capacity = 0;
    }

    vector& operator=(const vector& rhs) {
    
    
        return *this;
    }
    vector& operator=(vector&& rhs) {
    
    
        return *this;
    }

public:  // 涉及到指针的,需要考虑const版本
    // iterators
    iterator begin() noexcept {
    
    
        return this->m_data;
    }

    const_iterator begin() const noexcept {
    
    
        return this->m_data;
    }

    iterator end() {
    
    
        return this->m_data + this->m_size;
    }

    const_iterator end() const {
    
    
        return this->m_data + this->m_size;
    }

    // accessor
    value_type* data() noexcept {
    
    
        return this->data;
    }

    const value_type* data() const noexcept {
    
    
        return this->m_data;
    }

    size_type size() const noexcept {
    
    
        return this->m_size;
    }

    size_type capacity() const noexcept {
    
    
        return this->m_capacity;
    }

    bool empty() const noexcept {
    
    
        return this->m_size == 0;
    }

    // modifier
    void clear() noexcept {
    
    
        for (::size_t k = 0; k < this->m_size; k += 1) {
    
    
            this->m_data[k].~ValueT();
        }
        this->m_size = 0;
    }

    void pop_back() noexcept {
    
    
        // 保证size>0
        assert(!this->empty());

        ::size_t k = this->m_size - 1;
        this->m_data[k].~ValueT();
        this->m_size += -1;
    }

    void push_back(const ValueT& value) {
    
    
        this->emplace_back(value);
    }

    void push_back(ValueT&& value) {
    
    
        this->emplace_back(::std::move(value));
    }

    template <typename... Args>
    reference emplace_back(Args&&... args) {
    
    
        if (this->m_size < this->m_capacity) {
    
    
            // `data` can not be null
            ::size_t k = this->m_size;
            ::new (&this->m_data[k]) ValueT(::std::forward<Args>(args)...);
            this->m_size += 1;
            return this->m_data[k];
        }

        // 此时 size == capacity
        // 扩容1.5倍
        ::size_t new_capacity = this->m_size + 1;
        new_capacity |= this->m_size / 2;
        ::size_t new_size = 0;
        auto new_data =
            static_cast<ValueT*>(::operator new(new_capacity * sizeof(ValueT)));

        try {
    
    
            for (::size_t k = 0; k < this->m_size; k += 1) {
    
    
                // placement new
                // new时考虑异常
                ::new (&new_data[k]) ValueT(::std::move(this->m_data[k]));
                new_size += 1;
            }

            ::new (&new_data[new_size]) ValueT(::std::forward<Args>(args)...);
            new_size += 1;

        } catch (...) {
    
    
            for (::size_t k = 0; k < new_size; k += 1) {
    
    
                new_data[k].~ValueT();
            }
            ::operator delete(new_data);
            // 将异常重新抛出
            throw;
        }

        // 将原数据析构
        this->clear();
        ::operator delete(this->m_data);

        this->m_data = new_data;
        this->m_size = new_size;
        this->m_capacity = new_capacity;
        return new_data[new_size];
    }
};
}  // namespace my

int main() {
    
    
    ::my::vector<::std::string> vec;

    vec.push_back("hello");
    vec.emplace_back();
    vec.emplace_back("hello", 4);

    // 标准不禁止
    // vec.emplace_back(vec[0]);

    for (const auto& str : vec) {
    
    
        ::std::cout << str << ::std::endl;
    }

    return 0;
}

简单改良

真的,楼主感觉喵喵写已经非常优良和精简了。个人也只是做了简单的补充和注释。

比如补了一下赋值操作,简单封装了析构的功能函数等。


注意这里还是有很多情况没有考虑,以个人能力非要考虑的话也只能写出效率极低,冗余度高的丑陋代码

  • 如果考虑以迭代器为参数构造
    • 只能访问一次的迭代器该如何处理
  • 扩容时候插入的元素为原序列本身的元素
    • 扩容时移动到新空间错误
  • 部分new操作没考虑异常
  • 等等等等
#include <stddef.h>

#include <iostream>
#include <string>

namespace my {
    
    
template <class ValueT>
class vector {
    
    
public:
    using value_type = ValueT;
    using reference = ValueT&;
    using const_reference = const ValueT&;
    using iterator = ValueT*;
    using const_iterator = const ValueT*;
    using size_type = ::size_t;
    // 迭代器相减
    using difference_type = ::ptrdiff_t;

private:
    ValueT* m_data;
    ::size_t m_size;
    ::size_t m_capacity;

public:
    // 默认无参构造
    constexpr vector() noexcept : m_data(), m_size(), m_capacity() {
    
    
    }

    // 内存是vector自己管理的
    // 只想销毁对象
    ~vector() {
    
    
        this->destruct_this();
    }

    // 拷贝构造
    vector(const vector& rhs) {
    
    
        // 注意 operator new 会抛出异常
        this->m_data = static_cast<ValueT*>(
            ::operator new(rhs.m_capacity * sizeof(ValueT)));
        this->m_size = 0;
        this->m_capacity = rhs.m_capacity;

        try {
    
    
            for (::size_t k = 0; k < rhs->m_size; k += 1) {
    
    
                // new时考虑异常
                ::new (&this->m_data[k]) ValueT(rhs.m_data[k]);
                this->m_size += 1;
            }
        } catch (...) {
    
    
            destruct_this();
            throw;
        }
    }

    // 移动构造
    vector(vector&& rhs) {
    
    
        this->m_data = rhs.m_data;
        this->m_size = rhs.m_size;
        this->m_capacity = rhs.m_capacity;

        rhs.m_data = nullptr;
        rhs.m_size = 0;
        rhs.m_capacity = 0;
    }

    // 偷懒的写法
    vector& operator=(const vector& rhs) {
    
    
        auto tmp = rhs;
        using ::std::swap;
        swap(tmp, *this);
        return *this;
    }

    vector& operator=(vector&& rhs) {
    
    
        auto tmp = ::std::move(rhs);
        using ::std::swap;
        swap(tmp, *this);
        return *this;
    }

public:  // 涉及到指针的,需要考虑const版本
    // iterators
    iterator begin() noexcept {
    
    
        return this->m_data;
    }

    const_iterator begin() const noexcept {
    
    
        return this->m_data;
    }

    iterator end() {
    
    
        return this->m_data + this->m_size;
    }

    const_iterator end() const {
    
    
        return this->m_data + this->m_size;
    }

    // accessor
    value_type* data() noexcept {
    
    
        return this->data;
    }

    const value_type* data() const noexcept {
    
    
        return this->m_data;
    }

    size_type size() const noexcept {
    
    
        return this->m_size;
    }

    size_type capacity() const noexcept {
    
    
        return this->m_capacity;
    }

    bool empty() const noexcept {
    
    
        return this->m_size == 0;
    }

    // modifier
    void clear() noexcept {
    
    
        destruct_len(this->m_data, this->m_size);
        this->m_size = 0;
    }

    void pop_back() noexcept {
    
    
        // 保证size>0
        assert(!this->empty());

        ::size_t k = this->m_size - 1;
        this->m_data[k].~ValueT();
        this->m_size += -1;
    }

    // 调用 emplace_back
    void push_back(const ValueT& value) {
    
    
        this->emplace_back(value);
    }

    void push_back(ValueT&& value) {
    
    
        this->emplace_back(::std::move(value));
    }

    // 注意要使用完美转发
    template <typename... Args>
    reference emplace_back(Args&&... args) {
    
    
        if (this->m_size < this->m_capacity) {
    
    
            ::size_t k = this->m_size;
            ::new (&this->m_data[k]) ValueT(::std::forward<Args>(args)...);
            this->m_size += 1;
            return this->m_data[k];
        }

        // 此时 size == capacity
        // 扩容1.5倍
        ::size_t new_capacity = this->m_size + 1;
        new_capacity += this->m_size / 2;
        ::size_t new_size = 0;
        auto new_data =
            static_cast<ValueT*>(::operator new(new_capacity * sizeof(ValueT)));

        try {
    
    
            for (::size_t k = 0; k < this->m_size; k += 1) {
    
    
                // 并不是所有情况下的移动都是合理的
                ::new (&new_data[k]) ValueT(::std::move(this->m_data[k]));
                new_size += 1;
            }

            ::new (&new_data[new_size]) ValueT(::std::forward<Args>(args)...);
            new_size += 1;
        } catch (...) {
    
    
            destruct_len(new_data, new_size);
            ::operator delete(new_data);
            // 将异常重新抛出
            throw;
        }

        // 将原数据析构
        // 如果上面抛出异常了,这里可能把原数据全清了
        this->destruct_this();
        // 接管所有权
        this->m_data = new_data;
        this->m_size = new_size;
        this->m_capacity = new_capacity;
        return new_data[new_size];
    }

private:
    // 其实是析构的一个抽象
    void destruct_this() noexcept {
    
    
        this->clear();
        ::operator delete(this->m_data);
    }

    void destruct_len(ValueT* pdata, ::size_t len) noexcept {
    
    
        for (::size_t k = 0; k < len; k += 1) {
    
    
            pdata[k].~ValueT();
        }
    }
};
}  // namespace my

int main() {
    
    
    ::my::vector<::std::string> vec;

    vec.push_back("hello");
    vec.emplace_back();
    vec.emplace_back("hello", 4);

    // 标准不禁止
    // vec.emplace_back(vec[0]);

    for (const auto& str : vec) {
    
    
        ::std::cout << str << ::std::endl;
    }

    return 0;
}



END

猜你喜欢

转载自blog.csdn.net/CUBE_lotus/article/details/131387734