42_移动构造

移动构造

1.区分深拷贝和浅拷贝,C11添加了移动构造函数

ClassName(const ClassName& obj)拷贝构造

ClassName(ClassName&& obj)移动构造函数 右值引用

std::move,匹配移动构造,也可以强转类名加两个引用

std::swap,交换

2.解决链表匿名对象new和delete问题,移动构造设置大小为0,不会被重复释放

3.常量自动匹配右值引用

作业

1.动态数组模板(移动构造)
2.链表模板(移动构造)

 //Vector.h
#pragma once

template 
class CVector
{
public:

    CVector(const unsigned initCapacity = 1U)    //默认构造二个,其它构造为2倍
    {
        m_pElement = new T[initCapacity * 2];
        setSize(0U);
        setCapacity(initCapacity * 2);
    }

    CVector(const CVector& obj) //采用深拷贝,新的向量不会影响当前向量
    {
        m_pElement = new T[obj.getSize() * 2];

        for (unsigned i = 0; i < obj.getSize(); i++)
        {
            m_pElement[i] = obj.m_pElement[i];
        }

        setSize(obj.getSize());
        setCapacity(getSize() * 2);
    }

    CVector(CVector&& obj) //移动构造
    {
        setCapacity(obj.getSize());
        setSize(obj.getSize());
        m_pElement = obj.m_pElement;
        obj.m_pElement = nullptr;
    }

    ~CVector()
    {
        if (m_pElement != nullptr)
        {
            delete[] m_pElement;
        }
    }

    const bool isEmpty() const  //判断使用的空间是否为空,给用户提供判空方法
    {
        if (m_uSize != 0)
        {
            return false;
        }
        else
        {
            return true;
        }
    }

    CVector& push_back(const T& element)    //末尾添加元素
    {
        checkCapacity();
        //存放数据
        *(m_pElement + getSize()) = element;
        //设置使用的空间
        setSize(getSize() + 1U);
        return *this;
    }
    /*
    CVector& push_back(T&& element)
    {
        checkCapacity();
        //存放数据
        *(m_pElement + getSize()) = element;
        //设置使用的空间
        setSize(getSize() + 1U);
        //置空以前的
        element = NULL;
        return *this;
    }
    */

    CVector& pop_back() //末尾删除元素
    {
        //如果实际使用空间不为0
        if (getSize() != 0U)
        {
            setSize(getSize() - 1U);
        }

        return *this;
    }

    T& operator[](const int index) throw(...)   //重载下标获得值
    {
        if (!isEmpty())
        {
            return *(m_pElement + index);
        }
        else
        {
            throw 0;
        }
    }

    CVector& insert(const int pos, const T& obj)     //向指定位置增加元素
    {
        checkCapacity();
        //从后面元素移动到下一个元素移动以前的数据
        for (int i = (getSize() - 1); i >= pos; i--)
        {
            m_pElement[i + 1] = m_pElement[i];
        }
        //插入数据
        m_pElement[pos] = obj;
        //设置使用的空间
        setSize(getSize() + 1U);

        return *this;
    }

    CVector& insert(const int pos, T&& obj)     //向指定位置增加元素
    {
        checkCapacity();
        //从后面元素移动到下一个元素移动以前的数据
        for (int i = (getSize() - 1); i >= pos; i--)
        {
            m_pElement[i + 1] = m_pElement[i];
        }
        //插入数据
        m_pElement[pos] = obj;
        //以前的置空
        obj = (T)NULL;
        //设置使用的空间
        setSize(getSize() + 1U);

        return *this;
    }

    CVector& earse(const int pos)  //删除指定位置元素
    {
        if (getSize() > 0)
        {
            //从后面元素移动到下一个元素移动以前的数据
            for (int i = pos; i < (int)getSize() - 1; i++)
            {
                m_pElement[i] = m_pElement[i + 1];
            }
            //设置使用的空间
            setSize(getSize() - 1U);
        }
        return *this;
    }

    void notChange()    //暂时不修改大小了,把实际占用空间和使用的空间设为一样
    {
        if (getSize() == 0U && getCapacity() != 0U)
        {
            delete[] m_pElement;
            setCapacity(0U);
            m_pElement = nullptr;
        }
        else if (getSize() != getCapacity())
        {
            T *pOldElement = m_pElement;
            m_pElement = new T[getSize()];
            for (unsigned i = 0; i < getSize(); i++)
            {
                m_pElement[i] = pOldElement[i];
            }
            delete[] pOldElement;

            setCapacity(getSize());
        }
    }

    void clear()    //清空元素
    {
        setSize(0U);
    }

    CVector& operator+(const CVector& obj)  //合并两个向量
    {
        //复制数据
        CVector *pVec = new CVector((this->getSize() + obj.getSize()) * 2);
        unsigned vec = 0;
        for (unsigned i = 0; i < this->getSize(); i++, vec++)
        {
            pVec->m_pElement[vec] = this->m_pElement[i];
        }
        for (unsigned i = 0; i < obj.getSize(); i++, vec++)
        {
            pVec->m_pElement[vec] = obj.m_pElement[i];
        }
        //设置空间
        pVec->setCapacity((vec - 1u) * 2);
        pVec->setSize(vec - 1u);
        return *pVec;
    }

    CVector& operator+(CVector&& obj)  //合并两个向量
    {
        //复制数据
        CVector *pVec = new CVector((this->getSize() + obj.getSize()) * 2);
        unsigned vec = 0;
        for (unsigned i = 0; i < this->getSize(); i++, vec++)
        {
            pVec->m_pElement[vec] = this->m_pElement[i];
        }
        for (unsigned i = 0; i < obj.getSize(); i++, vec++)
        {
            pVec->m_pElement[vec] = obj.m_pElement[i];
        }
        //设置空间
        pVec->setCapacity((vec - 1u) * 2);
        pVec->setSize(vec - 1u);
        //以前的置空
        obj.clear();
        obj.m_pElement = nullptr;
        obj.setCapacity(0U);
        return *pVec;
    }

    T& back()
    {
        return m_pElement[getSize() - 1U];
    }

    T& front()
    {
        return m_pElement[0];
    }

    CVector& operator+= (CVector& vec)
    {
        for (int i = 0; i < vec.getSize(); i++)
        {
            push_back(vec[i]);
        }

        return *this;
    }
    
    CVector& operator+= (CVector&& vec)
    {
        for (int i = 0; i < vec.getSize(); i++)
        {
            push_back(vec[i]);
        }
        
        vec.clear();
        vec.m_pElement = nullptr;
        vec.setCapacity(0U);

        return *this;
    }


    unsigned getSize() const    //获取使用的空间
    {
        return m_uSize;
    }

    unsigned getCapacity() const    //获取实际占用空间
    {
        return m_uCapacity;
    }

private:
    void setSize(const unsigned size)   //设置使用的空间
    {
        m_uSize = size;
    }

    void setCapacity(const unsigned capacity)   //设置实际占用空间
    {
        m_uCapacity = capacity;
    }

    void checkCapacity()    //判断空间能否增加元素
    {
        //如果空间不够增加
        if (getSize() == getCapacity())
        {
            //设置旧的元素指针
            T *pOldElement = m_pElement;
            //设置实际存储空间为当前值的两倍
            setCapacity(getCapacity() * 2U);
            //申请新的占用空间
            m_pElement = new T[getCapacity()];
            //拷贝旧数据
            for (unsigned i = 0; i < getSize(); i++)
            {
                m_pElement[i] = pOldElement[i];
            }
            //清理掉以前的元素类型
            delete[] pOldElement;
        }
    }
private:
    T *m_pElement;      //存储的元素
    unsigned m_uSize;       //使用的空间
    unsigned m_uCapacity;   //实际占用空间
};
 //LinkList.h
#pragma once
#include 
using namespace std;

template  class CLinkList;

template 
class LinkNode //双向链表结点
{
public:
    LinkNode(T element = (T)0, LinkNode *previousNode = nullptr, LinkNode *nextNode = nullptr);
    ~LinkNode();
    friend class CLinkList;
public:
    T *m_pElement;
private:
    LinkNode *m_pPreviousNode;
    LinkNode *m_pNextNode;
};

template 
class CLinkList //双向链表类
{
public:
    CLinkList();
    CLinkList(T& element);                                                  //带参构造
    CLinkList(T&& element);                                                 //移动带参构造
    CLinkList(const CLinkList& obj);                                        //拷贝构造
    CLinkList(CLinkList&& obj);                                             //移动拷贝构造
    ~CLinkList();
    void test();                                                            //显示测试
    const unsigned getSize() const;                                         //获取链表大写
    void push_back(const T& element);                                       //尾结点增加元素
    void push_back(T&& element);                                            //尾结点移动增加元素
    void push_front(const T& element);                                      //头节点增加元素
    void push_front(T&& element);                                           //头节点移动增加元素
    LinkNode* insert(LinkNode* pos, const T& element);                //指定结点前增加元素
    LinkNode* insert(LinkNode* pos, T&& element);                     //指定结点前移动增加元素
    const bool empty() const;                                               //是否空链表
    void clear();                                                           //清空表
    void erese(LinkNode* pos);                                           //删除指定位置的元素
    void pop_back();                                                        //删除最后一个元素
    void pop_front();                                                       //删除第一个元素
    LinkNode* back();                                                    //获得最后一个元素
    LinkNode* front();                                                   //获得最第一个元素
    CLinkList& operator= (const CLinkList& list);                        //拷贝链表
    CLinkList& operator= (CLinkList&& list);                             //移动拷贝链表
    void operator+= (const CLinkList& list);                             //合并另一个链表到当前链表
    void operator+= (CLinkList&& list);                                  //移动合并另一个链表到当前链表
    //指定范围内删除
    //遍历抽象
private:
    void setSize(const unsigned size);                                      //设置大小

private:
    unsigned m_uSize;       //链表大小
    LinkNode *m_pHeadNode;  //头结点
    LinkNode *m_pTailNode;  //尾结点
};

template
LinkNode::LinkNode(T element, LinkNode * previousNode, LinkNode * nextNode)
{
    m_pElement = new T(element);
    m_pPreviousNode = previousNode;
    m_pNextNode = nextNode;
}

template
LinkNode::~LinkNode()
{
    if (m_pElement != nullptr)
    {
        delete m_pElement;
    }
}

template
CLinkList::CLinkList()
{
    m_pHeadNode = new LinkNode();                    //头结点
    m_pTailNode = new LinkNode();                    //尾结点
    m_pHeadNode->m_pNextNode = m_pTailNode;             //设置头结点
    m_pTailNode->m_pPreviousNode = m_pHeadNode;         //设置尾结点
    setSize(0U);                                        //大小为一
}

template
CLinkList::CLinkList(T& element)
{
    LinkNode *pNewNode = new LinkNode(element); //创建的新结点
    m_pHeadNode = new LinkNode(T(0));    //头结点
    m_pTailNode = new LinkNode(T(0));    //尾结点                                         
    m_pHeadNode->m_pNextNode = pNewNode;    //设置头结点    
    pNewNode->m_pPreviousNode = m_pHeadNode;    //设置新结点
    pNewNode->m_pNextNode = m_pTailNode;
    m_pTailNode->m_pPreviousNode = pNewNode; //设置尾结点
    setSize(1U);    //大小为一
}

template
CLinkList::CLinkList(T&& element)
{
    LinkNode *pNewNode = new LinkNode(element); //创建的新结点
    m_pHeadNode = new LinkNode(T(0));    //头结点
    m_pTailNode = new LinkNode(T(0));    //尾结点                                         
    m_pHeadNode->m_pNextNode = pNewNode;    //设置头结点    
    pNewNode->m_pPreviousNode = m_pHeadNode;    //设置新结点
    pNewNode->m_pNextNode = m_pTailNode;
    m_pTailNode->m_pPreviousNode = pNewNode; //设置尾结点
    setSize(1U);    //大小为一
    element = NULL;
}

template
CLinkList::CLinkList(const CLinkList& obj)
{
    m_pHeadNode = new LinkNode();    //头结点
    m_pTailNode = new LinkNode();    //尾结点
    m_pHeadNode->m_pNextNode = m_pTailNode; //设置头结点
    m_pTailNode->m_pPreviousNode = m_pHeadNode; //设置尾结点
                                                //拷贝的链表非空链表
    if (!obj.empty())
    {
        LinkNode *pNode = obj.m_pHeadNode->m_pNextNode;
        while (pNode->m_pNextNode != nullptr)
        {
            push_back(*(pNode->m_pElement));
            pNode = pNode->m_pNextNode;
        }
    }
    setSize(obj.getSize()); //设置大小
}

template
CLinkList::CLinkList(CLinkList&& obj)
{
    m_pHeadNode = obj.m_pHeadNode;
    m_pTailNode = obj.m_pTailNode;
    setSize(obj.getSize());

    obj.m_pHeadNode = nullptr;
    obj.m_pTailNode = nullptr;
    obj.setSize(0U);
}

template
CLinkList::~CLinkList()
{
    if (m_pHeadNode != nullptr && m_pTailNode != nullptr)
    {
        LinkNode *pNowNode = m_pHeadNode;
        LinkNode *pNextNode = nullptr;

        while (pNowNode->m_pNextNode != nullptr)
        {
            pNextNode = pNowNode->m_pNextNode;
            delete pNowNode;
            pNowNode = pNextNode;
        }

        delete pNowNode;
    }
}


template
void CLinkList::test()
{
    if (!empty())
    {
        cout << "list size:" << getSize() << endl;
        cout << "HeadDate:" << *m_pHeadNode->m_pElement;
        cout << ", HeadAddress:" << m_pHeadNode;
        cout << ", previousNode:" << m_pHeadNode->m_pPreviousNode;
        cout << ", nextNode address:" << m_pHeadNode->m_pNextNode << endl;

        LinkNode *pNode = m_pHeadNode->m_pNextNode;
        while (pNode->m_pNextNode != nullptr)
        {
            cout << "NodeDate:" << *pNode->m_pElement;
            cout << ", NodeAddress:" << pNode;
            cout << ", previousNode:" << pNode->m_pPreviousNode;
            cout << ", nextNode address:" << pNode->m_pNextNode << endl;

            pNode = pNode->m_pNextNode;
        }

        cout << "TailDate:" << *m_pTailNode->m_pElement;
        cout << ", TailAddress:" << m_pTailNode;
        cout << ", previousNode:" << m_pTailNode->m_pPreviousNode;
        cout << ", nextNode address:" << m_pTailNode->m_pNextNode << endl;
    }
}


template
void CLinkList::push_back(const T& element)
{
    LinkNode *pNode = new LinkNode(element);
    //设置当前结点的前驱与后继
    pNode->m_pPreviousNode = m_pTailNode->m_pPreviousNode;
    pNode->m_pNextNode = m_pTailNode;
    //设置尾结点的前驱结点的后继为当前结点
    m_pTailNode->m_pPreviousNode->m_pNextNode = pNode;
    //设置尾节点的前驱
    m_pTailNode->m_pPreviousNode = pNode;
    setSize(getSize() + 1U);
}

template
void CLinkList::push_back(T&& element)
{
    push_back(element);
    element = NULL;
}

template
void CLinkList::push_front(const T& element)
{
    LinkNode *pNode = new LinkNode(element);
    //设置当前结点的前驱与后继
    pNode->m_pPreviousNode = m_pHeadNode;
    pNode->m_pNextNode = m_pHeadNode->m_pNextNode;
    //设置头结点的后继结点的前继为当前结点
    m_pHeadNode->m_pNextNode->m_pPreviousNode = pNode;
    //设置头节点的后继
    m_pHeadNode->m_pNextNode = pNode;
    setSize(getSize() + 1U);
}

template
void CLinkList::push_front(T&& element)
{
    push_front(element);
    element = NULL;
}

template
const unsigned CLinkList::getSize() const
{
    return m_uSize;
}

template
void CLinkList::setSize(const unsigned size)
{
    m_uSize = size;
}

template
LinkNode* CLinkList::insert(LinkNode* pos, const T& element)
{
    LinkNode *pNode = new LinkNode(element);

    //设置新结点
    pNode->m_pPreviousNode = pos->m_pPreviousNode;
    pNode->m_pNextNode = pos;
    //设置旧结点的前继结点
    pos->m_pPreviousNode->m_pNextNode = pNode;
    //设置旧结点
    pos->m_pPreviousNode = pNode;
    setSize(getSize() + 1U);
    return pNode;
}

template
LinkNode* CLinkList::insert(LinkNode* pos, T&& element)
{
    LinkNode *pNode = new LinkNode(element);

    //设置新结点
    pNode->m_pPreviousNode = pos->m_pPreviousNode;
    pNode->m_pNextNode = pos;
    //设置旧结点的前继结点
    pos->m_pPreviousNode->m_pNextNode = pNode;
    //设置旧结点
    pos->m_pPreviousNode = pNode;
    setSize(getSize() + 1U);
    element = NULL;
    return pNode;
}

template
const bool CLinkList::empty() const
{
    if (getSize() != 0U)
    {
        return false;
    }
    else
    {
        return true;
    }
}

template
void CLinkList::clear()
{
    if (!empty())
    {
        LinkNode *pNowNode = m_pHeadNode->m_pNextNode;
        LinkNode *pNextNode = nullptr;

        while (pNowNode->m_pNextNode != nullptr)
        {
            pNextNode = pNowNode->m_pNextNode;
            delete pNowNode;
            pNowNode = pNextNode;
        }

        m_pHeadNode->m_pNextNode = m_pTailNode;
        m_pTailNode->m_pPreviousNode = m_pHeadNode;
        setSize(0U);
    }
}

template
void CLinkList::erese(LinkNode* pos)
{
    if (!empty())
    {
        pos->m_pPreviousNode->m_pNextNode = pos->m_pNextNode;
        pos->m_pNextNode->m_pPreviousNode = pos->m_pPreviousNode;
        setSize(getSize() - 1U);
        delete pos;
    }
}

template
void CLinkList::pop_back()
{
    if (!empty())
    {
        LinkNode *pNode = m_pTailNode->m_pPreviousNode;
        pNode->m_pPreviousNode->m_pNextNode = pNode->m_pNextNode;
        pNode->m_pNextNode->m_pPreviousNode = pNode->m_pPreviousNode;
        setSize(getSize() - 1U);
        delete pNode;
    }
}

template
void CLinkList::pop_front()
{
    if (!empty())
    {
        LinkNode *pNode = m_pHeadNode->m_pNextNode;
        pNode->m_pPreviousNode->m_pNextNode = pNode->m_pNextNode;
        pNode->m_pNextNode->m_pPreviousNode = pNode->m_pPreviousNode;
        setSize(getSize() - 1U);
        delete pNode;
    }
}

template
LinkNode* CLinkList::back()
{
    if (!empty())
    {
        LinkNode *pNode = m_pTailNode->m_pPreviousNode;
        return pNode;
    }
    else
    {
        return nullptr;
    }

}

template
LinkNode* CLinkList::front()
{
    if (!empty())
    {
        LinkNode *pNode = m_pHeadNode->m_pNextNode;
        return pNode;
    }
    else
    {
        return nullptr;
    }
}

template
CLinkList& CLinkList::operator= (const CLinkList& list)
{
    CLinkList *pLink = new CLinkList;
    CLinkList *pOldLink = this;

    if (!list.empty())
    {
        this->~CLinkList();
        LinkNode *pNode = list.m_pHeadNode->m_pNextNode;
        while (pNode->m_pNextNode != nullptr)
        {
            pLink->push_back(*(pNode->m_pElement));
            pNode = pNode->m_pNextNode;
        }
    }
    pLink->setSize(list.getSize());

    pOldLink->m_pHeadNode = pLink->m_pHeadNode;
    pOldLink->m_pTailNode = pLink->m_pTailNode;

    return *pLink;
}

template
CLinkList& CLinkList::operator=(CLinkList&& list)
{
    this->~CLinkList();

    m_pHeadNode = list.m_pHeadNode;
    m_pTailNode = list.m_pTailNode;
    setSize(list.getSize());

    list.m_pHeadNode = nullptr;
    list.m_pTailNode = nullptr;
    list.setSize(0U);

    return *this;
}

template
void CLinkList::operator+= (const CLinkList& list)
{
    if (!list.empty())
    {
        LinkNode *pNode = list.m_pHeadNode->m_pNextNode;
        while (pNode->m_pNextNode != nullptr)
        {
            push_back(*(pNode->m_pElement));
            pNode = pNode->m_pNextNode;
        }
    }
}

template
void CLinkList::operator+=(CLinkList&& list)
{
    if (!list.empty())
    {
        LinkNode *pNode = list.m_pHeadNode->m_pNextNode;
        while (pNode->m_pNextNode != nullptr)
        {
            push_back(*(pNode->m_pElement));
            pNode = pNode->m_pNextNode;
        }

        list.clear();
    }

    delete list.m_pHeadNode;
    delete list.m_pTailNode;

    list.m_pHeadNode = nullptr;
    list.m_pTailNode = nullptr;
}

 //homeWork.cpp
#include "LinkList.h"
#include "Vector.h"


int main()
{
    {
        CLinkList list;
        list.push_back(std::move(1));
        LinkNode *pNode = list.back();
        list.insert(pNode, 2);

        CLinkList list2;
        list2.push_back(3);
        list2.push_back(4);

        list2 = move(list);

        list2.test();
        list.test();
    }
    system("pause");
    return 0;
}

/*
template 
void test(CVector test)
{
    for (int i = 0; i < 40000000; i++)
    {
        test[i] = i + 1;
    }
}


int main()
{

    //CVector vec;
    
    
    for (int i = 0; i < 40000000; i++)
    {
        vec.push_back(i);
        //cout << vec[i] << endl;
    }
    */

    //test(std::move(vec));
    //test(vec);

    /*
    for (int i = 0; i < 10; i++)
    {
        vec.push_back(i);
    }

    CVector vec2;
    for (int i = 10; i < 20; i++)
    {
        vec2.push_back(i);
    }

    //vec2 += vec;
    vec2 += (std::move(vec));
    
    for (int i = 0; i < vec2.getSize(); i++)
    {
        cout << vec2[i] << " ";
    }

    cout << endl;

    for (int i = 0; i < vec.getSize(); i++)
    {
        cout << vec[i] << " ";
    }

    cout << endl;


    system("pause");
    return 0;
}
*/
0 条评论
发表一条评论