赋值操作符重载-C++复习二

赋值操作符重载

上篇文章着重讲述了复制构造函数的重要性,以及如果没有实现复制构造函数可能出现的致命错误,同时也指出赋值操作符重载在类中也和赋值构造函数一样重要.
但赋值操作符重载有着其独特的性质,本篇文章就专门介绍赋值操作符重载的一些性质,以及在实际开发中需要注意的地方.

引出问题

为了描述问题,我们简单设计一个类People, 包含三个成员m_pName, m_nAge, m_nGender,其中m_pName被声明为指向char类型的指针,用于保存姓名字符串.类头文件和cpp实现文件如下:
People.h

#ifndef PEOPLE_H
#define PEOPLE_H

class People
{
    public:
        People();
        People(const char *name, int age, int gender);
        //People(const People &pp);

        virtual ~People();

        People &operator=(const People &pp);

        void Print() const;
    protected:

    private:
        char *m_pName;
        int m_nAge;
        int m_nGender;
};

#endif // PEOPLE_H

People.cpp

#include "People.h"
#include <string.h>
#include <iostream>
using namespace std;

People::People()
{
    m_pName = new char[1];
    m_pName[0] = 0;
    m_nAge = 0;
    m_nGender = -1;
}

People::People(const char *name, int age, int gender)
{
    m_pName = new char[strlen(name)+1];
    strcpy(m_pName, name);
    m_nAge = age;
    m_nGender = gender;
}

//People::People(const People &pp)
//{
//    m_pName = new char[strlen(pp.m_pName)+1];
//    strcpy(m_pName, pp.m_pName);
//    m_nAge = pp.m_nAge;
//    m_nGender = pp.m_nGender;
//}

People::~People()
{
    delete []m_pName;
}

People &People::operator=(const People &pp)
{
    if(this == &pp)
    {
        return *this;
    }

    delete []m_pName;

    m_pName = new char[strlen(pp.m_pName)+1];
    strcpy(m_pName, pp.m_pName);
    m_nAge = pp.m_nAge;
    m_nGender = pp.m_nGender;

    return *this;
}

void People::Print() const
{

    std::cout<<"name:"<<m_pName<<endl;
    std::cout<<"age:"<<m_nAge<<endl;
    std::cout<<"gender:"<<m_nGender<<endl;
}

首先,我们吧复制构造函数注释掉,然后在main中调用People类的对象:
main.cpp

#include <iostream>

using namespace std;

#include "People.h"

int main()
{
    cout << "Hello world!" << endl;
    {
        People p("Emily", 28, 0);
        p.Print();

        People p1 = p;
        p1.Print();

        People p2;
        p2 = p1;
        p2.Print();
    }
    return 0;
}

运行main,结果输出如下图所示:
在这里插入图片描述从输出结果分析,程序对m_pName释放了两次,引发异常,程序崩溃.

分析

即使实现了赋值操作符重载,当使用形如"type_name obj_dst = obj_src;"这样的赋值语句对对象赋值时,程序仍然没有调用赋值操作符,而是调用了编译器默认提供的复制构造函数.
这是因为默认的复制构造函数形参只有一个,C++中对对象赋值时,将调用只有一个参数的构造函数,而此时这个构造函数正好与复制构造函数相匹配,所以调用了复制构造函数.但是我们在本例子中,把复制构造函数注释掉了,这样,程序就调用了编译器生成的复制构造函数,而默认的复制构造函数没有深拷贝m_pName成员,所以在析构函数被执行时,对象就试图delete不属于它创建的内存.

总结

必须实现复制构造函数,否则,只能使用先声明,后赋值的语法对对象赋值,如:
People p1(“Alex”, 30, 1);
PeoPle p2;
p2 = p1;
这时,重载的赋值操作符将被调用.

相关推荐
©️2020 CSDN 皮肤主题: 精致技术 设计师:CSDN官方博客 返回首页