zoukankan      html  css  js  c++  java
  • 构造函数/拷贝构造函数/赋值运算符/移动构造函数/移动赋值运算符几个的区别与相似之处

    构造函数:是类中用来声明初始化变量所用,在类定义的时候调用

    拷贝构造函数:在用其他已定义对象定义新对象的时候调用拷贝构造函数

    拷贝赋值运算符:在对象已经被初始化之后,再用其他已经定义的对象赋值就是调用拷贝赋值运算符。

    移动构造函数:与拷贝构造函数类似,但是不同之处在于他实现的是转移,源对象将丢失其内容,其内容将被目的对象所占有,移动操作发生在当移动对象为未命名对象的时候

    移动赋值运算符:与赋值运算符类似,但是不同之处在于他实现的是转移,源对象将丢失其内容,其内容将被目的对象所占有,移动操作发生在当移动对象为已命名对象的时候

    五个函数对比如下:

    函数名称

    源对象属性

    目的对象属性

    构造函数

    新对象

    拷贝构造函数

    已被初始化的对象

    未被初始化的对象

    拷贝赋值运算符

    已被初始化的对象

    已被初始化的对象

    移动构造函数

    临时对象(完成移动后将被注销)

    未被初始化的对象

    移动赋值运算符

    临时对象(完成移动后将被注销)

    已被初始化的对象

    例:

    // motioncontribute.cpp : Defines the entry pointfor the console application.
    //
     
    #include "stdafx.h"
    #include <iostream>
    #include <stdio.h>
    #include <string>
     
     
    using namespace std;
     
    class Pointer
    {
    public:
        Pointer(const int i, const string &n)
        {
            mptr =new int[i];
            length= i;
            name =n;
            cout<< "带参数构造函数
    ";
            showID();
        }//构造函数(有参)
        Pointer():mptr(nullptr), length(0){ cout << "无参数构造函数
    "; showID(); }//构造函数(无参)
        virtual ~Pointer()
        {
            cout<< name + "析构函数"<<endl;
            if (mptr)
                delete[] mptr;
            mptr =nullptr;
     
        }//析构函数
     
        Pointer(const Pointer& s)
        {
            length= s.getlen();
            mptr =new int[length];
            name =s.name;
            cout<< "复制构造函数
    ";
            showID();
        }//拷贝构造函数
        Pointer& operator=(const Pointer &s)
        {
            if (this == &s)
                return *this;
            if (mptr)
                delete[] mptr;
            length= s.getlen();
            mptr =new int[length];
            name =s.name;
            cout<< "赋值运算符
    ";
            showID();
            return *this;
        }//赋值运算符
     
        //移动构造函数,参数s不能是const Pointer&& s,因为要改变s的成员数据的值 
        Pointer(Pointer&& s)
        {
            length= s.getlen();
            mptr =s.getmptr();
            name =s.name + "_yidonggouzao";//调用移动构造函数时,加一个标记 
            s.mptr = nullptr;
            cout<< "移动构造函数
    ";
            showID();
        }//移动构造函数
     
        //移动赋值运算符 
        Pointer& operator=(Pointer&& s)
        {
            if (this == &s)
                return *this;
            if (mptr)
                delete[] mptr;
            length= s.getlen();
            mptr =s.mptr;
            name =s.name + "_yidongfuzhi";//调用移动赋值运算符时,加一个标记 
            s.mptr = nullptr;
            cout<< "移动赋值运算符
    ";
            showID();
            return *this;
        }//移动赋值运算符
     
        void showID()
        {
            cout<< "长度:" << length<< "  指针:" << mptr << "  名字:" << name<< endl;
        }
     
        int getlen() const
        {
            return length;
        }
     
        int* getmptr()const
        {
            return mptr;
        }
     
    private:
        int* mptr;
        int length;
        string name = "#NULL";//该参数用来标记不同的对象,c++11支持直接在类的数据成员定义处初始化 
    };
     
    Pointer test()
    {
        Pointer a(2, "test");
        return a;
    }
     
    int _tmain(int argc, _TCHAR* argv[])
    {
        //加花括号是为了观察析构函数的调用 
        {
            Pointer(4, "notname1");   //定义的临时对象,在调用完直接被析构
     
            Pointer a1 = test();//调用移动构造函数,创建对象a1 
            cout<< "a1.showID():
    ";
            a1.showID();
     
            Pointer a2;
            a2 = Pointer(5, "notname2");//调用移动赋值运算符 
     
            Pointer a3(Pointer(7, "notname3"));//此处没有调用移动构造函数,也就是说Pointer(7,"notname3") 这个变量没有被立即销毁(即不是临时变量),也许是因为它有了名字a3,所以不是临时变量了 
     
            cout<< "a3.showID():
    ";
            a3.showID();//验证a3确实是Pointer(7, "notname3") 
        }
        cout<< endl;
        system("pause");
        return 0;
    }


    输出结果为:

    带参数构造函数

    长度:指针:00A3F760  名字:notname1

    notname1析构函数

    带参数构造函数

    长度:指针:00A3F9C8  名字:test

    移动构造函数

    长度:指针:00A3F9C8  名字:test_yidonggouzao

    test析构函数

    a1.showID():

    长度:指针:00A3F9C8  名字:test_yidonggouzao

    无参数构造函数

    长度:指针:00000000  名字:#NULL

    带参数构造函数

    长度:指针:00A3F6F0  名字:notname2

    移动赋值运算符

    长度:指针:00A3F6F0  名字:notname2_yidongfuzhi

    notname2析构函数

    带参数构造函数

    长度:指针:00A3CC00  名字:notname3

    a3.showID():

    长度:指针:00A3CC00  名字:notname3

    notname3析构函数

    notname2_yidongfuzhi析构函数

    test_yidonggouzao析构函数

     

    参考资料:

    http://blog.csdn.net/shenwanjiang111/article/details/53576196

    http://blog.csdn.net/bupt8846/article/details/43833151

  • 相关阅读:
    Dom 笔记(二)
    HTML 笔记
    正则表达式学习下(转的呀不过刚用呢就收藏了)
    数据结构复习之【线性表】
    【毕业生】公司间的食物链
    所有获奖的英文名称——英文简历必备
    数据结构复习之【栈】
    BeanUtils学习总结
    SVN+TortoiseSVN+Subclipse使用总结
    JDK、JRE、JVM之间的关系
  • 原文地址:https://www.cnblogs.com/liumantang/p/11830390.html
Copyright © 2011-2022 走看看