• C++赋值运算符函数


    编写assigment赋值运算符函数时需注意几点:

    1. 返回值类型声明为该class的引用,为允许连续赋值(如可解析为右结合律的a=b=c),函数结束前应返回对象自身引用(*this);

    2. 传入参数类型应声明为该class的常量引用,因为1)如果传入的参数是实例,从形参到实参会调用一次赋值构造函数增大开销 2)加上const关键字避免改变传入参数对应实例;

    3. 注意释放该实例自身已有的内存,如果分配新内存前忘记释放已有的内存会造成内存泄漏;

    4. 应先判断传入参数对应的实例和*this是否为同一实例,如果相同则直接返回*this,不进行赋值操作。如果对与*this相同的实例进行赋值操作,释放自身内存时也同时会释放传入参数的内存,造成严重问题。

    经典解法:先判断传入参数是否为*this,若不是则先释放已有内存,再根据传入的参数分配新内存并对数据进行赋值,返回*this。

    CMyString& CMyString::operator=(const CMyString& str) {
        if(this == &str)
            return *this;
        delete []m_pData;
        m_pData = NULL;
        m_pData = new char[strlen(str.m_pData)+1];
        strcpy(m_pData, str.m_pData);
        return *this;
         
    }

    但此解法仍不具备异常安全性,如果因为分配时内存不足或copy函数抛出异常导致new()异常,持有指针可能会指向已被删除的对象。为让赋值运算符具备异常安全性,可在复制指针所指对象时,先不delete该指针,这样如果new()抛出异常,指针和指针原指的对象能够保持原状。

    CMyString& CMyString::operator=(const CMyString& str) {
        if(this==&str)
            return *this;
        char* pOrig = m_pData;
        m_pData = new char[strlen(str.m_pData)+1];
        strcpy(m_pData, str.m_pData);
        delete pOrig;
        return *this;
    }

    此外,还有一个办法是先创建一个临时实例,再交换临时实例和原来的实例,因为临时实例是一个局部变量,程序运行到区块结束就离开了该变量的作用域,临时变量的析构函数被自动调用,其指针指向的内存会被释放,也就释放了原先的m_pData指向的内存。

    CMyString& CMyString::operator=(const CMyString& str) {
        if(this == &str)
            return *this;
        CMyString strTemp(str);
        char* pTemp = strTemp.m_pData;
        strTemp.m_pData = m_pData;
        m_pData = pTemp;
        return *this;
    }

    完整代码:

    #include <iostream>
    #include <stdio.h>
    using namespace std;
    
    class CMyString {
      public:
        CMyString(char* pData = NULL);
        CMyString(const CMyString& str);
        ~CMyString(void);
        CMyString& operator=(const CMyString& str);
        void print();
      private:
        char* m_pData;
    };
    
    CMyString::CMyString(char* pData) {
        if(pData == NULL) {
            m_pData = new char[1];
            m_pData[0] = '';
        } else {
            int length = strlen(pData);
            m_pData = new char[length+1];
            strcpy(m_pData, pData);
        }
    }
    
    CMyString::CMyString(const CMyString& str) {
        int length = strlen(str.m_pData);
        m_pData = new char[length+1];
        strcpy(m_pData, str.m_pData);
    }
    
    CMyString::~CMyString(void) {delete []m_pData;}
    
    CMyString& CMyString::operator=(const CMyString& str) {
        if(this == &str)
            return *this;
        CMyString strTemp(str);
        char* pTemp = strTemp.m_pData;
        strTemp.m_pData = m_pData;
        m_pData = pTemp;
        return *this;
    }
    
    void CMyString::print() {
        cout << "The data is ";
        printf("%s
    ", m_pData);
    }
    
    
    int main() {
        char* text="sdlkjfskdfk";
        CMyString str1(text);
        cout << "str1: ";
        str1.print();
        CMyString str2(str1);
        cout << "-------do str2(str1)--------"<< endl;
        cout << "str2: ";
        str2.print();
        cout << "------------------------------" << endl << endl;
        
        CMyString str3="4534534534dd";
        cout << "str1: ";
        str1.print();
        cout << "str2: ";
        str2.print();
        cout << "str3: ";
        str3.print();
        cout << "--------do str1 = str2 = str3 --------" << endl;
        str1 = str2 = str3;
        cout << "str1: ";
        str1.print();
        cout << "str2: ";
        str2.print();
        cout << "str3: ";
        str3.print();
        cout << "---------------------------------" << endl << endl;
        cout << "str1: ";
        str1.print();
        cout <<"------------do str1 = str1 --------" << endl;
        str1 = str1;
        cout << "str1: ";
        str1.print();
        
    }

    参考资料:《剑指offer名企面试官精讲编程题》

  • 相关阅读:
    关于renren vue项目的启动
    idea得破解
    activiti任意节点任务跳转
    activiti的网关(GateWay)
    activiti入门案例
    activiti基本介绍
    事务的传播机制
    设计模式之鸭子模式
    Python中的数据类型
    tp5 模板参数配置:tpl_replace_string
  • 原文地址:https://www.cnblogs.com/RDaneelOlivaw/p/7344435.html
Copyright © 2020-2023  润新知