C++赋值操作符重载简介

原创 2015年11月21日 18:32:57

1.赋值操作符重载的原因

赋值操作符是一个使用频率最高的操作之一,通常情况下它的意义十分明确,就是将两个同类型的变量的值从一端(右端)传到另一端(左端)。但在以下两种情况下,需要对赋值操作符进行重载。
一是赋值号两边的表达式类型不一样,且无法进行类型转换。
二是需要进行深拷贝。

2. 赋值操作符重载的注意事项

赋值操作符只能通过类的成员函数的形式重载。这就说明了,如果要将用户自定义类型的值传递给基本数据类型的变量,只能通过类型转换机制,而不能利用重载来实现。

当赋值号两边的表达式不一致的时候,可能需要对赋值操作符进行重载,见下面的例子。

#include <iostream>
using namespace std;

class A{
    int num;
public:
    A(){num=0;}
    A(int i){num=i;}
    void show(){
        cout<<num<<endl;
    }
};

int main(int argc, char* argv[]){
    A a=5;       //符值符号两边的数据类型不一样,这里表示创建新对象
    a.show();
    A a1;
    a1=1;        //赋值号两边的数据类型不一样,这是真正的赋值运算
    a1.show();   
}

程序的输出结果是:
5
1

在语句A a=5中,虽然用到了“=”,但它的语义是构造一个类A的对象a,它等价于语句A a(5),所以该语句与赋值无关。而语句a1=1是一个真正的赋值语句,变量a1的类型是A,而常量1的类型是int,由于可以通过类A的构造函数A(int)将类型int转换成类型A(实际上是以int为参数构造了一个类A的临时对象),然后再完成赋值操作,所以不必再对赋值操作符进行重载。

3.深拷贝情况下对赋值操作符重载

深拷贝是对赋值操作符进行重载的有一个因素。那么什么是深拷贝呢?简单的说,深拷贝是在把一个类对象a拷贝到另一个对象b中去时,如果对象a中包含非悬挂指针(野指针),那么要将a的指针所指区域的内容拷贝到b的相应指针所指的区域中去。进行深拷贝时,一般对象a和b有相同的数据类型。如果在进行赋值时发生深拷贝,就一定要对赋值操作符进行重载,否则赋值运算符就会按赋值的常规语义进行(成员变量之间传递数据),而不发生深拷贝。考察如下例子。

#include <iostream>
using namespace std;

class Student{
    char* name;
    int age;
public:
    Student(){
        name=new char[20];
    }

    Student(char* n, int a){
        name=new char[20];
        if(name) strcpy(name,n);
        age=a;
    }

    Student(const Student& s){
        name=new char[20];
        *this=s;
    }
    void show(){
        cout<<"The student's name is "<<name;
        cout<<" and of age "<<age<<endl;
    }

    ~Student(){
        delete[] name;
    }

    Student& operator=(const Student &s){
        if(name) strcpy(name,s.name);
        age=s.age;
        return *this;
    }
};

int main(){
    Student s1("张三",18),s4("李四",20);
    Student s2;
    s1.show();
    s2=s4;
    s2.show();
    Student s3=s1;
    s3.show();
    return 0;
}

程序的输出结果是:
The student’s name is 张三 and of age 18
The student’s name is 李四 and of age 20
The student’s name is 张三 and of age 18

阅读以上程序,注意如下几点。
(1)由于在类Student中,存在指针成员name,所以,当两个Student类成员之间赋值时,必须使用深拷贝。执行s2=s4;语句,就是将s4对象赋值给s2,其中将s4.name字符串的内容拷入s2.name就是对深拷贝的具体体现。

(2)类的拷贝构造函数虽然与赋值操作符并不是一回事,但通常可以在拷贝构造函数中利用赋值操作符重载,以避免对两个对象之间传递数据的重复解释。

(3)上面的程序,直接使用strcpy(name,s.name);实现两个对象的字符串成员的数据传递。这是一种简化的做法,存在很多隐患。比如如果源字符串的长度超过20个字符,此程序会出现运行时错误。解决的办法是根据原字符串的长度,重新分配目的字符串的长度,再次之前还要释放目的字符串的空间。另外,一个对象赋值给自己,也会出现问题,需要进行源对象和目的对象地址的比较,再考虑赋不赋值。

(4)由于深拷贝会涉及到内存的动态分配和释放等一些较为复杂的操作,所以程序员在编写自定义类时要尽量避免深拷贝的出现。例如,在上例中,将成员变量name定义成string name,就可以避免自己编写实现深拷贝的代码。实际的深拷贝工作是由string类来完成,而string类是C++标准库提供的,我们可放心使用。

(5)最赋值操作符进行重载时,通常将操作符函数的返回值定义为赋值左操作数类型的引用。这是为了实现对赋值表达式的求值,还有一个目的就是为了实现链式操作。

版权声明:感谢您对博文的关注!2017年秋季校招已经开始,有需要内推腾讯的可以QQ(1589276509)联系我哈,期待你的加入。

C++库研究笔记——赋值操作符operator=的正确重载方式(三个准则)

C++ Operator Overloading Guidelines 设计要求: a, b, c, d, e; a = b = c = d = e = 42; This is inter...
  • mathgeophysics
  • mathgeophysics
  • 2013年07月30日 11:00
  • 5439

所有C++操作符重载的例子

1.[ ]操作符重载 C++语言规定:“[ ]”只能作为类的成员函数进行重载。 “[ ]”是C++中的下标运算符,对于数组或指针来说,下表运算的语义是确定的,不能进行重载。因此,如果看到一个运算...
  • chijianxingfeng
  • chijianxingfeng
  • 2013年04月30日 13:04
  • 2448

C++基础知识--赋值操作符重载

赋值运算符重载: 赋值运算符重载需要考虑什么问题: Class mystring {          Public:                    Mystring(char*pd...
  • yusiguyuan
  • yusiguyuan
  • 2014年12月19日 19:26
  • 605

C++ 重载操作符 operator

参数个数的限定     非成员函数:   单目运算符:参数表中只有一个参数;   双目运算符:参数表中只有两个参数       成员函数:   单目运算符:参数表中没有参数; ...
  • fenhong91
  • fenhong91
  • 2017年02月07日 09:55
  • 1021

重载赋值运算符

  重载赋值运算符赋值运算符可能是最容易令人迷惑的一个,所以,重载它必须十分的小心。1. 值运算符仅能重载为成员函数。C++不允许赋值运算符被重载为全局形式,这是因为如果可以写出全局形式的赋值运算符函...
  • wptad
  • wptad
  • 2007年07月22日 21:33
  • 10040

c++ 逗号操作符重载

Overload Operator Comma 首先看看think in c++ 给出的一个重载的例子 #include using namespace std; class After { ...
  • x356982611
  • x356982611
  • 2016年04月05日 12:32
  • 1636

C++类的赋值运算符“=”重载,以及深拷贝和浅拷贝

C++类的赋值运算符“=”重载,以及深拷贝和浅拷贝 在面向对象程序设计中,对象间的相互拷贝和赋值是经常进行的操作。 如果对象在申明的同时马上进行初始化操作,则称之为拷贝运算。例如: class1 A(...
  • liubing8609
  • liubing8609
  • 2014年11月23日 14:51
  • 2786

C++之派生类的拷贝构造与赋值运算符重载

这里只说一下为什么派生类在拷贝构造器和赋值运算符重载中一些注意语法: 一、派生类的拷贝构造器1.派生类的拷贝构造器跟普通构造器一样,若没有自定义生成,编译器会自动生成拷贝构造器,自动调用父类的拷贝构...
  • maoliran
  • maoliran
  • 2016年06月09日 19:28
  • 1830

C++运算符重载(11) - 重载<<和>>操作符

运算符 “>”用于流输出。 在开始重载这些操作符之前,必须注意下面的事项: 1) cout是输出类的对象,而cin是输入类的对象 2) 这些操作符必须重载为全局函数。如果想要让它们可以访问私有成员,...
  • shltsh
  • shltsh
  • 2015年05月27日 00:11
  • 931

赋值操作符重载

1 关于赋值的疑问 什么时候需要重载赋值操作符?编译器是否提供默认的赋值操作? 编译器为每个类默认重载了赋值操作符。 默认的赋值操作符仅完成浅拷贝。 当需要进行深拷贝时必须重载赋值操作符。 赋值...
  • qq_20233867
  • qq_20233867
  • 2018年02月08日 18:07
  • 16
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:C++赋值操作符重载简介
举报原因:
原因补充:

(最多只允许输入30个字)