重载=运算符

测试代码如下

#include <iostream>
#include <string>

using namespace std;

class StupidClass{
    int flag;
    string name;
    int* data;

public:

    StupidClass(int flag, string name) : flag(flag), name(name){
        cout << "Constructor " << flag << " " << name << endl;
        data = new int;
        *data = flag * 3;
    }

    ~StupidClass(){
        cout << "Destructor " << flag << " " << name << " " << data << endl;
        if (data != nullptr)
        {
            delete data;
        }
    }
/*  
    StupidClass(const StupidClass&  rhs){
        this->flag = rhs.flag;
        this->name = rhs.name;
        data = new int;
        *data = flag * 3;
        cout << "Copy Constructor *this=" << flag << " rhs.flag=" << rhs.flag << endl;
        cout << "Copy Constructor *this=" << name << " rhs.name=" << rhs.name << endl;
    }
*/

    StupidClass& operator=(const StupidClass& rhs){
        this->flag = rhs.flag;
        this->name = rhs.name;
        data = new int;
        *data = flag * 3;
        cout << "Operator = *this=" << flag << " rhs.flag=" << rhs.flag << endl;
        cout << "Operator = *this=" << name << " rhs.name=" << rhs.name << endl;
        return *this;
    }
};


int main()
{
    StupidClass var1(1, "var1"), var2(2, "var2");
    //StupidClass var3 = var1;

    return 0;
}

问题是这样的,在执行StupidClass var3 = var1;这一句时,我以为是调用重载=运算符,但是实际情况是调用了复制拷贝函数,很奇怪。
当我把复制拷贝函数注释掉的,单步调试,执行上述语句的时候,并没有进入到重载=运算函数的内部,直接跳到下一步,也没用进到其他函数内部,然后接着程序崩溃了。
崩溃的地方是在调用第三次析构的时候出错了。
运行
发现第三次析构的地址和第一次是一样的,应该是多次析构同一个指针
那为什么var1和var3的data指针的地址一样呢?

首先StupidClass var3 = var1;在这里是要调用拷贝构造函数的,不会调用重载的=运算符,如果是:
StupidClass var3;
var3 = var1;
这里就会调用重载=运算符。

StupidClass var3 = var1;这里应该是调用了浅层拷贝构造函数,仅仅是简单的一对一的复制拷贝,所以var1和var3的data所指向的地址是一样的。
所以当类的成员比较复杂的时候,最好还是要有一个深层构造函数。

/*******************string.h*************************/

#ifndef STRING_H
#define STRING_H

#include <iostream>

class String {
    friend std::ostream& operator<<(std::ostream& os, const String& str);
public:
    String(const char* cstr = 0);
    String(const String& str);
    ~String();

    String& operator=(const String& str);

    char* get_c_str() const { return m_data; }
private:
    char* m_data;
};


#endif

/*******************string.cpp**********************/

#include "string.h"
#include <cstring>


String::String(const char * cstr)
{
    if (cstr) {
        m_data = new char[strlen(cstr) + 1];
        strcpy(m_data, cstr);
    }
    else {
        m_data = new char[1];
        *m_data = '\0';
    }
}

String::String(const String & str)
{
    m_data = new char[strlen(str.m_data) + 1];
    strcpy(m_data, str.m_data);
}

String::~String()
{
    delete[] m_data;
}

String & String::operator=(const String & str)
{
    // 自我赋值
    if (this == &str)
        return *this;

    delete[] m_data;
    m_data = new char[strlen(str.m_data) + 1];
    strcpy(m_data, str.m_data);

    return *this;
}

std::ostream& operator<<(std::ostream& os, const String& str)
{
    os << str.get_c_str();
    return os;
}

/*******************string.cpp**********************/

#include <iostream>
#include "string.h"

int main()
{
    String s1("Hello World"), s2("I love you");
    String s3 = s1;   //调用深层拷贝函数
    String s4;
    s4 = s1;          //调用赋值拷贝函数
    std::cout << s3 << std::endl;

    return 0;
}

注:本人正在学习状态,文中多有引用,也有解释纰漏之处,敬请包涵、指正!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值