move_construction代码(构造函数, 移动, 析构, 深浅拷贝)

move_construction代码

系统默认提供的拷贝构造函数的工作方式是内存拷贝—浅拷贝
浅拷贝: 如果复制的对象中引用以一个外部内容(例如分配在堆上的数据),那么在复制这个对象的时候,让新旧对象指向同一个外部内容,就是浅拷贝。(指针虽然复制了,但所指向的空间内容并没有复制,而是由两个对象共用,两个对象不独立,删除弓箭存在问题)。调用析构函数时会将该指针指向的数据析构两次,造成错误。

深拷贝:如果在复制这个对象的时候为新对象制作了外部对象的独立复制,就是深拷贝。

复制构造函数需为指针变量分配内存空间,并将实参的值拷贝到其中;而赋值操作符它实现的功能仅仅是将‘=’号右边的值拷贝至左值,在左边对象内存不足时,先释放然后再申请。当然赋值操作符必须检测是否是自身赋值,若是则直接返回当前对象的引用而不进行赋值操作

line.h

#ifndef LINE_H
#define LINE_H
#include <string>
#include <iostream>

class Line
{
public:
    Line(int lineNo);
    ~Line(){ std::cerr << "  delete a line.";}

    void writeChar(std::string chars);
    std::string chars(){return m_chars;}
private:
    int m_no;
    std::string m_chars;
};

#endif // LINE_H

page.h

#ifndef PAGE_H
#define PAGE_H
#include <vector>
#include "line.h"

class Page
{
public:
    Page(int no, int lines);
    Page(const Page &o);
    Page(Page &&o) noexcept;
    Page &operator= (const Page &o);
    Page &operator=(Page &&o) noexcept;
    ~Page();

    Line *getLine(int lineNo){
        return _lines[lineNo - 1];
    }
    auto lines(){ return _lines; }
private:
    int m_no;
    std::vector<Line *> _lines;
};

#endif // PAGE_H

line.cpp

#include "line.h"
#include <exception>
using std::domain_error;
using std::string;

Line::Line(int lineNo):m_no{lineNo}{
    if(lineNo < 1)
        throw domain_error("invalid line number.");
}

void Line::writeChar(string chars){
    m_chars = chars;
}


page.cpp

#include "page.h"
#include <iostream>
#include <exception>
using std::domain_error;
using std::cerr;

Page::Page(int no, int lines):m_no{no}
{
    if(no < 1)
        throw domain_error("invalid line number.");

    for(int i = 1; i < lines + 1; i++)
        _lines.push_back(new Line(i));

    cerr << "  call Page's parameter constructor.";
    cerr << " The "<< m_no
         <<" Page has " << _lines.size() << " lines now.\n";
}

Page::Page(const Page &o):
    m_no{o.m_no}
{
    for(auto l:o._lines)
        _lines.push_back(new Line{*l});
    cerr << "  call Page's copy constructor.";
    cerr << " This Page has " << _lines.size() << " lines now.\n";
}


Page::Page(Page &&o)noexcept:
    m_no{o.m_no},_lines{o._lines} //普通成员复制,资源成员浅复制
{
    o._lines.clear();             //资源成员完成资源移动
    cerr << "  call Page's move constructor.";
    cerr << " The "<< m_no
         <<" Page has " << _lines.size() << " lines now.\n";
}

//深赋值
Page &Page::operator=(const Page &o)
{
    cerr << "  call Page's operator=(Page &).";
    m_no=o.m_no;  //普通成员赋值

//    cerr << "  _lines=" <<_lines.size() <<  " before erase,";
    for(auto l:_lines)  //资源成员深赋值-擦除左值资源
        delete l;
    _lines.clear();
//    cerr << "  o._lines=" <<o._lines.size() <<  " before copy,";
    for(auto l:o._lines) //资源成员深赋值-复制
        _lines.push_back(new Line{*l});
//    cerr << "  o._lines=" << o._lines.size() <<  " after copy,";
//    cerr << "  _lines="<< _lines.size() << " now.\n";

    return *this;
}

//移动赋值
Page &Page::operator=(Page &&o) noexcept
{
    for(auto l:_lines)  //清理左值对象的资源
        delete l;

    m_no=o.m_no;        //普通成员赋值
    _lines = o._lines;  //资源成员浅赋值
    o._lines.clear();   //资源成员完成资源移动

    return *this;       //返回赋值表达式的值
}

Page::~Page()
{
    cerr << "  call Page's destructor.";
    for(auto &l:_lines){
        delete l;
        l = nullptr;
    }
    cerr << " This Page had " << _lines.size() << " lines before.\n";
}

main.cpp

#include <iostream>
#include "page.h"
#include "line.h"

using namespace std;

Page p0(5,10);

Page f()
{
    Page p(3, 2);
    cerr << "  in the f().\n";
    p.getLine(1)->writeChar("hello");
    return p;
}

Page g()
{
    cerr << "  in the g().\n";
    return Page(4, 2);
}


int main()
{
    cerr << "\n1 Page p1 = Page(1,2);" << endl;
    Page p1 = Page(1,2); //默认省略移动操作,直接触发参数构造函数

    cerr << "\n2 Page p2 {Page(2,3)};" << endl;
    Page p2 {Page(2,3)};//默认省略移动操作,直接触发参数构造函数

    cerr << "\n3 Page p3 = p1;" << endl;
    Page p3 = p1;        //触发复制构造函数

    cerr << "\n4 Page p4 {p1};" << endl;
    Page p4 {p2};        //触发复制构造函数

    cerr << "\n5 Page p5 = std::move(p3);" << endl;
    Page p5 = std::move(p3); //显式触发移动构造函数

    cerr << "Page p3 has " <<
            p3.lines().size() << " lines now." << endl;

    cerr << "\n6 Page p6 {std::move(p4)};" << endl;
    Page p6 {std::move(p4)}; //显式触发移动构造函数
    cerr << "    Page p4 has " << p4.lines().size() << " lines now."<<endl;

    cerr << "\n7 Page p7 = std::move(Page(2,2));" << endl;
    Page p7 = std::move(Page(2,2));//显式触发移动构造函数

    cerr << "\n8 Page p8 {std::move(Page(3,2))};" << endl;
    Page p8 {std::move(Page(3,2))};//显式触发移动构造函数

    cerr << "\n9 Page p9 {f()};" << endl;
    Page p9 {f()};//默认省略移动操作,但可能被优化掉

    cerr << "\n10 Page p10 {g()};" << endl;
    Page p10 {g()};//默认省略移动操作,但可能被优化掉

    cerr << "\n11 Page &&p11 {f()};" << endl;
    Page &&p11 {f()};//默认省略移动操作,但可能被优化掉

    cerr << "\n12 p1 = p2" << endl;
    p1 = p2;//触发operator=(Page &)复制赋值操作

    cerr << "\n13 p1 = Page(2,2);" << endl;
    p1 = Page(2,2);//触发operator=(Page &&)移动赋值操作


    cerr << "\n\n------brefore return 0;---------\n";

    return 0;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值