簡體   English   中英

嘗試在 operator= 上使用復制和交換習語

[英]Trying to use copy and swap idiom on operator=

在嘗試實施 MyVector 時,我最終得到:

#include <iostream>
#include <string>

using namespace std;

template <typename T>
class MyVector
{
    int m_size = 0;
    int m_capacity = 0;

    T* m_data = nullptr;

public:
    MyVector()
    {
        cout << "defautl ctor" << endl;

        realloc(2);
    }

    MyVector(const MyVector& v)
    : m_size(v.m_size), 
      m_capacity(v.m_capacity)
    {
        cout << "copy ctor" << endl;

        m_data = new T[m_size];
        *m_data = *v.m_data;
    }

    MyVector(MyVector&& v)
    : m_size(v.m_size), 
      m_capacity(v.m_capacity)
    {
        cout << "move ctor" << endl;

        m_data = move(v.m_data);

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

    MyVector& operator= (const MyVector& v)
    {
        cout << "copy assignment operator" << endl;

        // m_size = v.m_size;
        // m_capacity = v.m_capacity;
        // *m_data = *v.m_data;

        MyVector<int> copy = v;
        swap(*this, copy);

        return *this;
    }

    void push_back(const T& value)
    {

        if (!(m_size < m_capacity))
        {
            // cout << value << " size is " << m_size << " capacity is " << m_capacity << endl;

            realloc(m_size*2);
            // return;
        }

        m_data[m_size++] = value;
    }

    T& operator[] (int index)
    {
        cout << "index " << index << " of size " << m_size << endl;

        if (!(index < m_size))
            cout << "index out of bounds" << endl;

        return m_data[index];
    }

    int size()
    {
        return m_size;
    }

    T* begin()
    {
        return &m_data[0];
    }

    T* end()
    {
        return &m_data[size()];
    }

private:
    void realloc(int new_capacity)
    {
        // cout << __func__ << " new capacity " << new_capacity << endl;

        T* data = new T[new_capacity];

        for (int i = 0; i < m_size; i++)
            data[i] = m_data[i];

        delete[] m_data;
        m_data = data;

        m_capacity = new_capacity;
    }
};


int main(int argc, char** argv)
{
    cout << "starting..." << endl;

    MyVector<int> a;
    a.push_back(7);

    MyVector<int> d;
    d = a; 

    cout << a[0] << endl;
    cout << d[0] << endl;

    return 0;
}

其中operator=

    MyVector& operator= (const MyVector& v)
    {
        cout << "copy assignment operator" << endl;

        // m_size = v.m_size;
        // m_capacity = v.m_capacity;
        // *m_data = *v.m_data;

        MyVector<int> copy = v; // copy and swap
        swap(*this, copy);

        return *this;
    }

然而,這導致了似乎是遞歸行為。 那么,我對復制和交換方法的理解是錯誤的嗎? 還是我還缺少其他東西?

如評論中所述,您沒有為 MyVector 實現swap() MyVector ,因此語句swap(*this, copy); 正在調用std::swap() (使用using namespace std;眾多陷阱之一),這將再次調用您的operator= ,因此您會看到遞歸行為。

此外,您的復制構造函數未正確實現。 它不會將輸入數組中的所有元素復制到新數組中。 它只復制第一個元素。

此外,您還缺少釋放分配數組的析構函數。

此外,由於MyVector具有復制和移動構造函數,因此您的兩個賦值operator=可以(並且應該)合並為一個按值獲取MyVector的運算符。 這讓編譯器可以根據調用者分別傳入左值還是右值來決定是調用具有復制語義還是移動語義的運算符。 然后操作員可以swap任何給定的內容,因為在輸入操作員之前輸入已經被復制或移動。

嘗試更像這樣的東西:

#include <iostream>
#include <string>
#include <algorithm>
#include <stdexcept>

template <typename T>
class MyVector
{
    int m_size = 0;
    int m_capacity = 0;
    T* m_data = nullptr;

public:
    MyVector()
    {
        std::cout << "default ctor" << std::endl;

        realloc(2);
    }

    MyVector(const MyVector& v)
    {
        std::cout << "copy ctor" << std::endl;

        realloc(v.m_capacity);
        std::copy_n(v.m_data, v.m_size, m_data);
        m_size = v.m_size;
    }

    MyVector(MyVector&& v)
    {
        std::cout << "move ctor" << std::endl;

        v.swap(*this);
    }

    ~MyVector()
    {
        std::cout << "dtor" << std::endl;

        delete[] m_data;
    }

    MyVector& operator= (MyVector v)
    {
        std::cout << "assignment operator" << std::endl;

        v.swap(*this);

        return *this;
    }

    void push_back(const T& value)
    {
        if (m_size >= m_capacity)
        {
            // std::cout << value << " size is " << m_size << " capacity is " << m_capacity << std::endl;

            realloc(m_size * 2);
        }

        m_data[m_size] = value;
        ++m_size;
    }

    T& operator[] (int index)
    {
        std::cout << "index " << index << " of size " << m_size << std::endl;

        if (index < 0 || index >= m_size)
            throw std::out_of_range("index out of bounds");

        return m_data[index];
    }

    int size() const
    {
        return m_size;
    }

    T* begin()
    {
        return &m_data[0];
    }

    T* end()
    {
        return &m_data[m_size];
    }

    void swap(MyVector &other)
    {
        std::swap(m_data, other.m_data);
        std::swap(m_size, other.m_size);
        std::swap(m_capacity, other.m_capacity);
    }

private:
    void realloc(int new_capacity)
    {
        // std::cout << __func__ << " new capacity " << new_capacity << std::endl;

        T* data = new T[new_capacity];

        std::copy_n(m_data, m_size, data);
        std::swap(m_data, data);
        m_capacity = new_capacity;

        delete[] data;
    }
};

// for std::swap() to use via ADL...
void swap(MyVector &v1, MyVector &v2)
{
    v1.swap(v2);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM