c/c++赋值函数(重载=号运算符)

首先c++里的各种运算符都是用函数实现的,比如=,就等号函数。

所以当用=给一个对象赋值的时候,实际调用的是=号所对应的=号函数。

分析下面的代码

#include <iostream>
using namespace std; class Test{
public:
explicit Test(){
data = 0;
}
explicit Test(int d):data(d){
cout << "C:" << this << ":"<< this->data << endl;
}
//拷贝构造函数
Test(const Test &t){
cout << "Copy:" << this << endl;
data = t.data;
}
//重载=号运算符
Test& operator= (const Test &t){
cout << "assign" << this << endl;
if(this != &t){
data = t.data;
}
return *this;
}
~Test(){
cout << "F:" << this << ":" << this->data << endl;
}
private:
int data;
};
int main(){
Test t1(10);
Test t2, t3; t3 = t2 = t1; return 0;
}

重点分析下面的函数

  //重载=号运算符
Test& operator = (const Test &t){
cout << "assign" << this << endl;
if(this != &t){
data = t.data;
}
return *this;
}

分析点:

1,operator =是什么意思

2,参数为什么是引用类型

3,参数为什么有const限制

4,为什么有if(this != &t)的判断

5,为什么有返回值

6,为什么返回值的类型是引用类型

分析点解答:

Test t2;

t2 = t1;//实际的运作方式是t2.operator=(t1),所以函数里面的this就是t2

1,重载类Test的=号函数,当对类Test的对象用=号操作的时候,就会调用这个重载后的函数

2,避免调用拷贝构造函数

3,避免不小心修改里参数t里面成员变量的值(t.data = 100;)

4,防止自己给自己赋值

5,为了能够使用 t3 = t2 = t1。如果没有返回值,则t3.operator=(t2=t1),的参数里面t2=t1就没有返回值,所以编译不过。

6,不是引用也可以,用引用类型是防止老版本的编译器,在return处调用拷贝构造函数,新版本的编译器(gcc 4.8.5-20),即使不用引用类型,就不会调用拷贝构造函数。

一个大大的疑问,求高人指点

下面代码,重载了=号函数,故意把fun函数的返回值类型设置为引用,t2 = fun(t1);的执行结果:t2的data还是0,符合常理。

#include <iostream>
using namespace std; class Test{
public:
Test(int d = 0):data(d){
cout << "C:" << d << " " << this << endl;
}
Test(Test &t){
cout << "Copy:" << t.data << " " << this << endl;
data = t.data;
} Test& operator = (const Test &t){
cout << "Assign:" << this << " = " << &t << endl;
if(this != &t){
data = t.data;
}
return *this;
} ~Test(){
cout << "F:" << this->data << "->" << this << endl;
}
int getData()const{
return data;
}
private:
int data;
}; Test& fun(Test &x){
int value = x.getData();
Test tmp(value);
return tmp; } int main(){
Test t1(100);
Test t2;
t2 = fun(t1);
cout << t2.getData() << endl;
//Test t2 = fun(t1); return 0;
}

但是,注释掉重载的=号函数,故意把fun函数的返回值类型设置为引用,t2 = fun(t1);的执行结果:t2的data居然是100,不符合常理,求高人指点

#include <iostream>
using namespace std; class Test{
public:
Test(int d = 0):data(d){
cout << "C:" << d << " " << this << endl;
}
Test(Test &t){
cout << "Copy:" << t.data << " " << this << endl;
data = t.data;
}
/*
Test& operator = (const Test &t){
cout << "Assign:" << this << " = " << &t << endl;
if(this != &t){
data = t.data;
}
return *this;
}
*/ ~Test(){
cout << "F:" << this->data << "->" << this << endl;
}
int getData()const{
return data;
}
private:
int data;
}; Test& fun(Test &x){
int value = x.getData();
Test tmp(value);
return tmp; } int main(){
Test t1(100);
Test t2;
t2 = fun(t1);
cout << t2.getData() << endl;
//Test t2 = fun(t1); return 0;
}

c/c++赋值函数(重载=号运算符)的更多相关文章

  1. C++ //多态 //静态多态:函数重载 和 运算符重载 属于静态多态 ,复用函数名 //动态多态:派生类和虚函数实现运行时多态

    1 //多态 2 //静态多态:函数重载 和 运算符重载 属于静态多态 ,复用函数名 3 //动态多态:派生类和虚函数实现运行时多态 4 5 //静态多态和动态多态的区别 6 //静态多态的函数地址早 ...

  2. 深入理解c++构造函数, 复制构造函数和赋值函数重载(operator=)

    注 以下代码编译及运行环境均为 Xcode 6.4, LLVM 6.1 with GNU++11 support, Mac OS X 10.10.2 调用时机 看例子 // // main.cpp / ...

  3. C++友元函数重载"++"和"--"运算符

    代码: #include <iostream> #include <cstring> using namespace std; class one{ public: one(i ...

  4. C++ //运算符重载 +号

    1 #include <iostream> 2 #include <string> 3 using namespace std; 4 5 //1.成员函数重载 +号 6 cla ...

  5. C++:成员运算符重载函数和友元运算符重载函数的比较

    5.2.4 成员运算符重载函数和友元运算符重载函数的比较 (1)对双目运算符而言,成员运算符重载函数参数表中含有一个参数,而友元运算符重载函数参数表中有两个参数:对于单目运算符而言,成员运算符重载函数 ...

  6. C++:运算符重载函数之成员运算符重载函数

    5.2.3 成员运算符重载函数 在C++中可以把运算符重载函数定义为某个类的成员函数,称之为成员运算符重载函数. 1. 定义成员运算符重载函数的语法形式 (1)在类的内部,定义成员运算符重载函数的格式 ...

  7. C++:运算符重载函数之友元运算符重载

    5.2.2 友元运算符重载函数 运算符重载函数一般采用两种形式定义: 一是定义为它将要操作的类的成员函数(简称运算符重载函数): 二是定义为类的友元函数(简称为友元运算符重载函数). 1.定义友元运算 ...

  8. C++第五次作业--运算符重载和函数重载

    C++ 运算符重载和函数重载 C++ 允许在同一作用域中的某个函数和运算符指定多个定义,分别称为函数重载和运算符重载. 重载声明是指一个与之前已经在该作用域内声明过的函数或方法具有相同名称的声明,但是 ...

  9. C++类中的一些细节(重载、重写、覆盖、隐藏,构造函数、析构函数、拷贝构造函数、赋值函数在继承时的一些问题)

    1 函数的重载.重写(重定义).函数覆盖及隐藏 其实函数重载与函数重写.函数覆盖和函数隐藏不是一个层面上的概念.前者是同一个类内,或者同一个函数作用域内,同名不同参数列表的函数之间的关系.而后三者是基 ...

随机推荐

  1. CentOS7 Hadoop 3.1.0 编译安装

    1.配置环境变量 JAVA_HOME=/jdk1..0_131 ANT_HOME=/apache-ant- MAVEN_HOME=/apache-maven- FINDBUGS_HOME=/findb ...

  2. Java中的Interrupt使用

    初心 用interrupt中断程序 初步实现 public class InterruptionInJava implements Runnable{ @Override public void ru ...

  3. 如何用Python编写一个聊天室

    一.课程介绍 1.简介 本次项目课是实现简单聊天室程序的服务器端和客户端. 2.知识点 服务器端涉及到asyncore.asynchat和socket这几个模块,客户端用到了telnetlib.wx. ...

  4. 解决QTableWidget不显示数据的问题

    QTableWidget通常用于数据的展示,通过其表格布局可以让用户更清晰的查看数据,同时也让数据的筛选变得更加直观. 不过,初学者们和粗心大意的人总是会发现明明自己数据已经正常添加,可是程序运行之后 ...

  5. 查看内置命令和非内置命令帮助的几种方法(man、help、info)

    内置命令就是shell内核自带的,因为shell当中自己要进行管理,那么就需要一些命令进行管理,不同的shell肯定有不同的shell命令,我们用type命令就可以看到其的类型,内置shell命令其实 ...

  6. JS实现分钟数和时间小时 格式的转换

    1.分钟数转换为 小时:分钟  function ChangeHourMinutestr(str) { if (str !== "0" && str !== &qu ...

  7. Prism 学习:从本地目录加载 Module

    在 Prism 中,将外部模块加载到主程序有以下几种方式:Code.XAML.配置文件.指定模块目录:其中,如果要使用 Code 方式来加载 Module,则需要将该 Module 引用到当前项目中: ...

  8. 47.Linux-DEVICE_ATTR()介绍及使用示例

    1.介绍 使用DEVICE_ATTR,可以实现驱动在sys目录自动创建文件,我们只需要实现show和store函数即可. 然后在应用层就能通过cat和echo命令来对sys创建出来的文件进行读写驱动设 ...

  9. sping框架纯注解配置

    1.相关注解 ①@Configuration注解-->添加了该注解在类上,就表明该类是spring的配置类.该类的作用是用来替代原来的XML配置文件的. 通过配置类创建容器时,需要使用Annot ...

  10. 如何用ftp上传静态网站到虚拟空间

    ftp是一种网络传输协议,你要上传网站到空间首先你要安装一个FTP软件,你申请的空间有一个网址.账号.密码之类的,你打开FTP输入这些链接就可以准备上传网站了,软件打开有一个本地界面,还有一个空间界面 ...