首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用smart_pointers的属向量类

使用smart_pointers的属向量类
EN

Code Review用户
提问于 2018-08-08 00:44:28
回答 1查看 123关注 0票数 1

我决定重写我所做的这里,遵循使用智能指针的建议。我还将酌情使用智能指针重写其他数据结构。

我只想看看我的代码现在的状况,我确信还有一些地方我需要改进或修复。我想再次感谢这个社区在评估我的代码时所做的努力,我真的很感激它,我相信它正在缓慢但肯定地将我的编码技能提升到更高的水平。

以下是我的头文件:

代码语言:javascript
复制
#ifndef Vector_h
#define Vector_h



template <class T>
class Vector {
private:

    static constexpr int initial_capacity = 100;

    // Instance variables
    int capacity = 0;
    int size = 0;
    std::unique_ptr<T[]> data = nullptr;

    void deepCopy(const Vector<T> &source) {
        capacity = source.size + initial_capacity;
        data = std::make_unique<T[]>(capacity);
        for (int i = 0; i < source.size; i++) {
            data[i] = source.data[i];
        }
        size = source.size;
    }

    void expandCapacity() {
        auto oldData = std::move(data);
        capacity *= 2;
        data = std::make_unique<T[]>(capacity);
        for (int i = 0; i < size; i++) {
            data[i] = oldData[i];
        }
    }

public:

    // Constructors
    Vector();                                           // empty constructor
    Vector(int n, const T &value);                      // constructor
    Vector(Vector<T> const &vec);                       // copy constructor
    Vector<T>& operator=(Vector<T> const &rhs);         // assignment operator

    // Rule of 5
    Vector(Vector<T> &&move) noexcept;                  // move constructor
    Vector& operator=(Vector<T> &&move) noexcept;       // move assignment operator
    ~Vector();                                          // destructor

    // Overload operators
    T& operator[](int index);
    T const& operator[](int index) const;
    bool operator==(const Vector<T>&) const;

    Vector<T>& operator+=(const Vector<T> &other) {
        Vector<T> newValue(size + other.size);

        std::copy(this->data, this->data + this->size, newValue.data);
        std::copy(other.data, other.data + other.size, newValue.data + this->size);

        newValue.swap(*this);
    }

    friend Vector<T>& operator+(Vector<T> &source1, Vector<T> &source2) {
        int n = source1.getSize() + source2.getSize();
        Vector<T> newSource(n,0);
        for (int i = 0; i < source1.size; i++) {
            newSource[i] = source1[i];
        }

        for (int i = 0; i < source2.size; i++) {
            newSource[i + source1.getSize()] = source2[i];
        }

        return newSource;
    }

    friend std::ostream& operator<<(std::ostream &str, Vector<T> &data) {
        data.display(str);
        return str;
    }

    // Member functions
    void swap(Vector<T> &other) noexcept;
    void display(std::ostream &str) const;
    int getSize() const { return size; }
    int getCapacity() const { return capacity; }
    bool empty() const { return size == 0; }
    void clear() { size = 0; }
    T get(int index) const;
    void set(int index, const T &value);
    void set(int index, T &&value);
    void insert(int index, const T &value); 
    void insert(int index, T &&value);
    void remove(int index);
    void push_back(const T &value);
    void pop_back();

};

template <class T>
Vector<T>::Vector() : capacity(initial_capacity), size(0), data{ new T[capacity] } {}

template <class T>
Vector<T>::Vector(int n, const T &value) {
    capacity = (n > initial_capacity) ? n : initial_capacity;
    data = std::make_unique<T[]>(capacity);
    size = n;
    for (int i = 0; i < n; i++) {
        data[i] = value;
    }
}

template <class T>
Vector<T>::Vector(Vector<T> const &vec) {
    deepCopy(vec);
}

template <class T>
Vector<T>::Vector(Vector<T> &&move) noexcept {
    move.swap(*this);
}

template <class T>
Vector<T>& Vector<T>::operator=(Vector<T> const &rhs) {
    Vector<T> copy(rhs);
    swap(copy);
    return *this;
}

template <class T>
Vector<T>& Vector<T>::operator=(Vector<T> &&move) noexcept {
    move.swap(*this);
    return *this;
}

template <class T>
Vector<T>::~Vector() {
    while (!empty()) {
        pop_back();
    }
}

template <class T>
T& Vector<T>::operator[](int index) {
    return data[index];
}

template <class T>
T const& Vector<T>::operator[](int index) const {
    return data[index];
}

template <class T>
bool Vector<T>::operator==(const Vector<T> &rhs) const {
    if (getSize() != rhs.getSize()) {
        return false;
    }
    for (int i = 0; i < getSize(); i++) {
        if (data[i] != rhs[i]) {
            return false;
        }
    }
    return true;
}

template <class T>
void Vector<T>::swap(Vector<T> &other) noexcept {
    using std::swap;
    swap(capacity, other.capacity); 
    swap(size, other.size);
    swap(data, other.data);
}

template <class T>
void Vector<T>::display(std::ostream &str) const {
    for (int i = 0; i < size; i++) {
        str << data[i] << "\t";
    }
    str << "\n";
}

template <class T>
T Vector<T>::get(int index) const {
    if (index < 0 || index >= size) {
        throw std::out_of_range("[]: index out of range.");
    }
    return data[index];
}

template <class T>
void Vector<T>::set(int index, const T& value) {
    if (index < 0 || index >= size) {
        throw std::invalid_argument("set: index out of range");
    }
    data[index] = value;
}

template <class T>
void Vector<T>::set(int index, T&& value) {
    if (index < 0 || index >= size) {
        throw std::invalid_argument("set: index out of range");
    }
    data[index] = std::move(value);
}

template <class T>
void Vector<T>::insert(int index, const T& value) {
    if (size == capacity) {
        expandCapacity();
    }

    for (int i = size; i > index; i--) {
        data[i] = data[i - 1];
    }
    data[index] = value;
    size++;
}

template <class T>
void Vector<T>::insert(int index, T&& value) {
    if (size == capacity) {
        expandCapacity();
    }

    if (index < 0 || index >= size) {
        throw std::invalid_argument("insert: index out of range");
    }

    for (int i = size; i > index; i--) {
        data[i] = data[i - 1];
    }
    data[index] = std::move(value);
    size++;
}

template <class T>
void Vector<T>::remove(int index) {
    if (index < 0 || index >= size) {
        throw std::invalid_argument("insert: index out of range");
    }

    for (int i = index; i < size - 1; i++) {
        data[i] = data[i + 1];
    }
    size--;
}

template<class T>
void Vector<T>::push_back(const T& value) {
    insert(size, value);
}

template<class T>
void Vector<T>::pop_back() {
    remove(size - 1);
}

#endif /* Vector_h */

下面是main.cpp文件:

代码语言:javascript
复制
#include <algorithm>
#include <initializer_list>
#include <iostream>
#include <cassert>
#include <ostream>
#include "Vector.h"


int main() {

    ///////////////////////////////////////////////////////////////////////
    ///////////////////////////// VECTOR //////////////////////////////////
    ///////////////////////////////////////////////////////////////////////
    Vector<int> nullVector;                        // Declare an empty Vector
    assert(nullVector.getSize() == 0);                 // Make sure its size is 0
    assert(nullVector.empty());                    // Make sure the vector is empty
    assert(nullVector.getCapacity() == 100);          // Make sure its capacity is greater than 0

    Vector<int> source(20, 0);                      // Declare a 20-element zero Vector
    assert(source.getSize() == 20);                 // Make sure its size is 20
    for (int i = 0; i < source.getSize(); i++) {
        source.set(i, i);
        assert(source.get(i) == i);                 // Make sure the i-th element has value i
    }



    source.remove(15);                              // Remove the 15th element
    assert(source[15] == 16);                       // Make sure the 15th element has value 16
    source.insert(15, 15);                          // Insert value 15 at the index 15
    assert(source[15] == 15);                       // Make sure the 15th element has value 15

    source.pop_back();                              // Remove the last element
    assert(source.getSize() == 19);                 // Make sure its size is 19
    source.push_back(19);                           // Insert value 20 at the bottom
    assert(source.getSize() == 20);                 // Make sure its size is 20
    assert(source.get(19) == 19);                   // Make sure the 19th element has value 19

    Vector<int> copyVector(source);                 // Declare a Vector equal to source
    for (int i = 0; i < source.getSize(); i++) {
        assert(copyVector[i] == source[i]);         // Make sure copyVector equal to source
    }

    std::cout << "source: \n" << source;            // Print out source
    std::cout << "copyVector: \n" << copyVector;    // Print out copyVector
    //Vector<int> newSource = source + copyVector;    //  Concatenate source and copyVector
    //std::cout << "newSource: \n" << newSource;      // Print out source + copyVector

    source.clear();                                 // Clear source
    assert(source.getSize() == 0);                  // Make sure its size is 0

    std::cout << "Vector unit test succeeded." << std::endl;



    std::cin.get();
}
EN

回答 1

Code Review用户

发布于 2018-08-08 13:08:48

代码语言:javascript
复制
data = std::make_unique<T[]>(capacity);
size = n;

撇开实际应该在一个init列表中完成这件事相比,这里您创建了100个对象,但声称您只拥有它们的n。虽然对于简单的类型来说,这并不总是一个好情况(设想一个对象,在默认情况下,它会在海外创建到默认地址的TCP连接)。使data成为未初始化的存储,并根据需要将对象存储在其中可能更有意义。

票数 3
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/201171

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档