(C++) STL 向量实现

(c++) stl vector implemenation

提问人:martin 提问时间:3/13/2019 最后编辑:Jarod42martin 更新时间:3/13/2019 访问量:91

问:

我已经实现了一个简单的类似向量的结构 如果我使用,它工作得很好,但是当我使用它时会出错 我的代码中是否有关于向量 stl 或问题的良好实现代码?vector<int>vector<char><vector<vector<int>>

这是我的代码

class _vector {
private:
    int _size;
    int _capacity;
    T* vc;

public:
    _vector(int size = 1) {
        _size = 0;
        _capacity = size;
        vc = new T[size];
    }
    ~_vector() {
        delete[] vc;
    }
    int size() { return _size; }
    bool empty() { return !_size; }
    void resize(int size) {
        _capacity = size;
        T* tmp = new T[size];
        for (int i = 0; i < _size; i++) tmp[i] = vc[i];
        delete[] vc;
        vc = tmp;
    }
    void clear() {
        delete[] vc;
        _capacity = 1;
        _size = 0;
        vc = new T[_capacity];
    }
    void push_back(T val) {
        if (_size == _capacity) resize(2 * _capacity);
        vc[_size++] = val;
    }
    void pop_back() {
        if (_size == 0) return;
        vc[--_size] = 0;
    }
    T& operator[](int i) const { return vc[i]; }
    _vector<T>& operator=(_vector<T> &tmp) {
        _capacity = tmp._capacity;
        _size = tmp._size;
        delete[] vc;
        vc = new T[_capacity];
        for (int i = 0; i < _size; i++) vc[i] = tmp[i];
        return *this;
    }
C++ 向量 三分法

评论

0赞 PaulMcKenzie 3/13/2019
1) 变量名称不要以下划线开头。2)它工作得很好 - 不,它没有。如果它不能与某种类型一起使用,那么代码中就存在根本缺陷。3) 你的复制构造函数在哪里?这是你的类中缺少的基本功能。
0赞 Dmytro Dadyka 3/13/2019
它犯了什么错误?
0赞 PaulMcKenzie 3/13/2019
另外,一个显示您如何使用类的函数怎么样?还有这个: -- 为什么不简单地设置为 0?无需重新分配内存。mainvoid clear()size
2赞 PaulMcKenzie 3/13/2019
此外,赋值运算符未正确实现。但在此之前,只需实现复制构造函数 -- 如果您使用 copy/swap 惯用语,赋值运算符将很容易实现
2赞 Remy Lebeau 3/13/2019
@PaulMcKenzie标准向量不仅仅是设置 .它必须销毁从内部数组中删除的项目。这个向量类需要做同样的事情。当是一个非平凡类型时,这一点很重要,比如说,另一个向量,比如OP在这个问题中要问的。clear()size=0T

答:

0赞 Remy Lebeau 3/13/2019 #1

您的实现没有遵循 3 法则,因为它缺少一个复制构造函数和一个正确的复制赋值运算符(可以使用复制构造函数实现)。在 C++ 11 及更高版本中,通过添加移动构造函数和移动赋值运算符,使用 5 法则。

此外,您的实现无法正确处理定义了构造函数/析构函数的非平凡类型,例如 when is another type,或在其内部分配了指针/资源的任何其他类型的类型。因此,在向数组添加元素时,类需要构造新对象,使用 ,并在从数组中删除元素时通过直接调用它们的析构函数来析构对象。T_vectorplacement-new

尝试更像这样的东西:

template <typename T>
class _vector {
public:
    typedef unsigned int size_type;
    typedef T value_type;

private:
    size_type _size;
    size_type _capacity;
    value_type* vc;

public:
    _vector(size_type initalcap = 0) : _size(0), _capacity(0), vc(0) {
        reserve(initialcap);
    }

    _vector(const _vector<T> &src) : _size(0), _capacity(0), vc(0) {
        reserve(src._capacity);
        for(size_type i = 0; i < src._size; ++i) {
            new(vc[i]) value_type(src.vc[i]);
        }
        _size = src._size;
    }

    // C++11 and later only...
    _vector(_vector<T> &&src) : _size(src._size), _capacity(src._capacity), vc(src._vc) {
        src._size = 0;
        src._capacity = 0;
        src.vc = 0;
    }

    ~_vector() {
        clear();
        delete[] reinterpret_cast<char*>(vc);
    }

    size_type size() const { return _size; }
    size_type capacity() const { return _capacity; }
    bool empty() const { return !_size; }

    void reserve(size_type newcap) {
        if (newcap <= _capacity) return;
        value_type* tmp = reinterpret_cast<value_type*>(new char[sizeof(value_type) * newcap]);
        for (size_type i = 0; i < _size; ++i) {
            new(tmp[i]) value_type(vc[i]);
        }
        delete[] reinterpret_cast<char*>(vc);
        vc = tmp;
        _capacity = newcap;
    }

    void resize(size_type newsize) {
        if (newsize < _size) {
            for(size_type i = _size; i-- > newsize; ) {
                vc[i].~value_type();
            }
            _size = newsize;
        }
        else if (newsize > _size) {
            reserve(newsize);
            for (size_type i = _size; i < newsize; ++i) {
                 new(vc[i]) value_type();
            }
            _size = newsize;
        }
    }

    void clear() {
        resize(0);
    }

    void push_back(const T &val) {
        if (_size == _capacity) reserve(2 * _capacity);
        new(vc[_size]) value_type(val);
        ++_size;
    }

    void pop_back() {
        if (_size) {
            vc[--_size].~value_type();
        }
    }

    value_type& operator[](size_type i) { return vc[i]; }
    const value_type& operator[](size_type i) const { return vc[i]; }

    _vector<T>& operator=(const _vector<T> &rhs) {
        if (&rhs != this) {
            _vector<T> tmp(rhs);
            std::swap(tmp.vc, vc);
            std::swap(tmp._size, _size);
            std::swap(tmp._capacity, _capacity);
        }
        return *this;
    }

    // C++11 and later only...
    _vector<T>& operator=(_vector<T> &&rhs) {
        _vector<T> tmp(std::move(rhs));
        std::swap(tmp.vc, vc);
        std::swap(tmp._size, _size);
        std::swap(tmp._capacity, _capacity);
        return *this;
    }
};

评论

0赞 martin 3/13/2019
我真的很感谢你的帮助。我研究过没有 STL 的算法。所以我必须练习 stl 实现。
1赞 Red.Wave 3/15/2019
@martin IMFO 中,您需要学习C++习语 1st(复制+交换、3/5 规则、RAII...)以及模式 - 特别是C++特定的 1(CRTP...)。然后才开始模拟一些 STL 特征。