[練習] Copy-and-Swap Pattern

Reference: http://stackoverflow.com/questions/3279543/what-is-the-copy-and-swap-idiom

#include <iostream>
#include <cassert>


template<typename T>
class DummyArray
{public:
    // Default Constructor
    DummyArray(size_t size = 0):m_size(size), m_data(new T[size]())
    {};
    
    // Copy Constructor
    DummyArray(const DummyArray<T>& da)
        :m_size(da.m_size), m_data(new T[da.m_size]())
    {
        // `The main copy each items logic` only happens here, no duplicate self. 
        std::copy(da.m_data, da.m_data + da.m_size, m_data); 
    }
    
    // Move Constructor
    DummyArray(DummyArray<T>&& da)
        :m_size(0), m_data(new T[0]()) // prepare null data to swap to moved parameter
    {
        swap(da); // invoke swap helper method
    }
    
    // Copy Assignment
    DummyArray& operator=(DummyArray<T> da_copy) // invoke copy constructor in parameter
    {        
        swap(da_copy); // invoke Swap helper method
        return *this;
    }
    
private:
    // Swap Helper
    void swap(DummyArray<T>& da)
    {
        std::swap(m_size, da.m_size);
        std::swap(m_data, da.m_data);
    }
    
public:
    
    // Virtual Destructor
    virtual ~DummyArray()
    {
        delete [] m_data;
    }
    
    // Members Getters
    size_t size() const
    {
        return m_size;
    };
    
    const T& at(size_t index) const
    {
        return m_data[index];
    }
    bool setItem(size_t i, const T& item)
    {
        m_data[i] = item;
    }
    
    // Valid Check Method
    explicit operator bool() const
    {
        return m_data != nullptr && m_size != 0;
    }
    bool operator!() const
    {
        return (*this)?false:true;
    }
    
private:
    size_t m_size = 0;
    T* m_data = nullptr;
};
template<typename T>
void AssertEqual(const DummyArray<T>& da, const DummyArray<T>& da2)
{
    std::cout << "running equal assertion...." << std::endl;
    assert(da);
    std::cout << "da is valid" << std::endl;
    assert(da2);
    std::cout << "da2 is valid" << std::endl;
    assert(da.size() == da2.size());    
    std::cout << "size is equal." << std::endl;
    for(int i = 0 ; i < da.size(); i++)
    {
        assert(da.at(i) == da2.at(i));      
        std::cout << i << " item is equal." << std::endl;
    }
    std::cout << "passed" << std::endl << std::endl;
}


template<typename T>
void AssertMoved(const DummyArray<T>& da)
{
    std::cout << "running empty assertion...." << std::endl;
    assert(da.size() == 0);
    std::cout << "da size is 0." << std::endl;
    assert(!da);
    std::cout << "da is invliad." << std::endl;
    std::cout << "passed" << std::endl << std::endl;    
}

int main()
{
   DummyArray<int> da(5);
   for(int i=0;i<5;i++)
     da.setItem(i, i+100);

   DummyArray<int> da2 = da;
   AssertEqual(da2, da);
     
   DummyArray<int> da3;
   da3 = da;
   AssertEqual(da3, da);
   
   DummyArray<int> da4;
   da4 = std::move(da2);
   AssertEqual(da4, da);
   AssertMoved(da2);
   
   DummyArray<int> emptyDa(0);
   AssertMoved(emptyDa);
   
   return 0;
}

心得:
用了 swap, Code 真的少寫很多,也安全許多。自己慢慢建出來,跟範例的不太一樣的地方,似乎是範例的 swap 是對稱型 free function 的,而我的是 member function 形式的,不知道差別在哪裡。

comments powered by Disqus