zoukankan      html  css  js  c++  java
  • C++中的复制、赋值、析构

    一直对C++的复制(Copy)、赋值(Assign)操作比较困惑,现在看书的时候看到了,就把它顺便记下来。

    一、什么时候触发

    一下代码可以熟悉什么时候触发复制操作,以及什么时候触发赋值操作:

    // testCopy.cpp : 定义控制台应用程序的入口点。
    //
    
    #include "stdafx.h"
    #include <iostream>
    #include <string>
    
    using namespace std;
    class testCopy
    {
    public:
        testCopy():a(0)
        {
            cout<<"enter constructor"<<endl;
        };
        //重载赋值操作符
        testCopy& operator=(const testCopy& t)
        {
            cout<<"enter operator="<<endl;
            a = t.a;
            return *this;
        }
        //复制构造函数
        testCopy(const testCopy& t):a(t.a)
        {
            cout<<"enter copy constructor"<<endl;
        }
        ~testCopy()
        {
            cout<<"enter destructor"<<endl;
        }
        int a;
    };
    
    void f1(testCopy t2)
    {
        cout<<"enter f1"<<endl;
    }
    
    testCopy f2()
    {
        cout<<"enter f2"<<endl;
        testCopy t3;//调用普通构造函数
        return t3;//以类实例为非引用类型返回值时触发复制构造
    }
    
    int _tmain(int argc, _TCHAR* argv[])
    {
        cout<<"t1"<<endl;
        testCopy t1;//调用普通构造函数
        cout<<"t2"<<endl;
        testCopy t2(t1);//直接以类实例为参数初始化另一个类实例时触发复制构造
        cout<<"t3"<<endl;
        testCopy t3;//调用普通构造函数
        t3 = t1;//将类实例赋值给另一个类实例时触发赋值操作
        cout<<"f1"<<endl;
        f1(t1);//以类实例为非引用类型的参数传递给函数时调用复制构造
        cout<<"f2"<<endl;
        testCopy t4;//调用普通构造函数
        t4 = f2();//将类实例赋值给另一个类实例时触发赋值操作
        cout<<"end"<<endl;
        return 0;
    }

    输出结果如下:

    t1
    enter constructor
    t2
    enter copy constructor
    t3
    enter constructor
    enter operator=
    f1
    enter copy constructor
    enter f1
    enter destructor
    f2
    enter constructor
    enter f2
    enter constructor
    enter copy constructor
    enter destructor
    enter operator=
    enter destructor
    end
    enter destructor
    enter destructor
    enter destructor
    enter destructor

    二、复制、赋值、析构函数重写的必要性

    上面的例子不足以说明重写复制、赋值、析构的重要性,当类中需要动态分配内存时,重要性就体现出来了:

    class testCopy2
    {
    public:
        testCopy2():buf(new char[128])
        {
            cout<<"enter constructor"<<endl;
        };
        //重载赋值操作符
        testCopy2& operator=(const testCopy2& t)
        {
            //如果不重写赋值构造函数,那么多个类实例之间的buf指向的是同一片内存。
            cout<<"enter operator="<<endl;
            memcpy(buf,t.buf,128);
            return *this;
        }
        //复制构造函数
        testCopy2(const testCopy2& t):buf(new char[128])
        {
            cout<<"enter copy constructor"<<endl;
            memcpy(buf,t.buf,128);
            //如果不重写复制构造函数,那么多个类实例之间的buf指向的是同一片内存。
        }
        ~testCopy2()
        {
            //如果不重写析构函数,那么buf指针内存不会被删除。
            cout<<"enter destructor"<<endl;
            delete buf;
        }
        char* buf;
    };

    三、一些规则

    1. 如果一个类需要一个析构函数,那么它一定需要重载复制和赋值操作。

    2. 如果一个类需要重载复制操作,那么它一定需要重载赋值操作,反之同成立。

    3. 如果一个类需要重载复制和赋值操作,但是不一定需要重载析构操作。

    四、相关下载

    代码

  • 相关阅读:
    Tomcat example 应用信息泄漏漏洞及修复
    Tomcat远程代码执行漏洞(CVE-2017-12615)修复
    Oracle安装和使用说明
    关于乱码的问题
    js 判断字符串中是否包含某个字符串
    com.alibaba.fastjson.JSONPathException: expect '], but 'y'
    java.util.UnknownFormatConversionException: Conversion = ''';
    nested exception is java.lang.NoClassDefFoundError: org/codehaus/jettison/json/JSONObject异常的解决办法
    复选框做成单选的效果
    sFlow-rt安装部署
  • 原文地址:https://www.cnblogs.com/Reyzal/p/5457485.html
Copyright © 2011-2022 走看看