`
java-mans
  • 浏览: 11386766 次
文章分类
社区版块
存档分类
最新评论

用汇编的眼光看C++(之算术符重载陷阱)

 
阅读更多

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】


在算术符重载里面,“=”重载可能是最经常使用的一种。但是好多人就误以为在函数中,凡是类出现“=”的地方,那就是调用算术符重载,其实不然。为什么呢?我们可以看看下面的代码。首先,我们定义一个基本类:

class data
{
	char* value;
	int number;
public:
	explicit data(int num = 0){
		if(num){
			number = num;
			value = (char*)malloc(num);
		}
	}

	data(const data& d){
		number = d.get_number();
		value = (char*)malloc(d.get_number());
		memmove(value, d.get_point(), d.get_number());
	}

	~data(){
		if(number)
			free(value);
	}

	data& operator=(const data& d){
		if(number)
			free(value);
		number = d.get_number();
		value = (char*)malloc(d.get_number());
		memmove(value, d.get_point(), d.get_number());
		return *this;
	
	}

	int get_number() const {return number;}
	char* get_point() const {return value;}
};

定义好了函数之后,我们就开始对这个类进行调用,同样代码如下所示:

45:       data m(10);
0040108D   push        0Ah
0040108F   lea         ecx,[ebp-14h]
00401092   call        @ILT+30(data::data) (00401023)
00401097   mov         dword ptr [ebp-4],0
46:       data p = m;
0040109E   lea         eax,[ebp-14h]
004010A1   push        eax
004010A2   lea         ecx,[ebp-1Ch]
004010A5   call        @ILT+35(data::data) (00401028)
004010AA   mov         byte ptr [ebp-4],1
47:       p = m;
004010AE   lea         ecx,[ebp-14h]
004010B1   push        ecx
004010B2   lea         ecx,[ebp-1Ch]
004010B5   call        @ILT+5(data::operator=) (0040100a)
48:   }
上面共有三句话,我们逐一进行分析:

45句:定义了一个临时变量,调用data的构造函数

46句:出现了一个临时变量p,这里发现data类并没有调用算术符重载函数,而是调用了data的构造函数,根据45句所示,调用的肯定不是普通的构造函数,那么剩下的结果只能是拷贝构造函数

47句: 和46句的代码是一致的,但是此时调用的函数才是算术符重载函数

所以说,出现“=”的地方未必调用的都是算术符重载函数,也有可能是拷贝构造函数。那么什么时候是拷贝构造函数,什么时候是算术符重载函数呢?判断的标准其实很简单。如果临时变量是第一次出现,那么调用的只能是拷贝构造函数,反之如果变量已经存在,就像47句一样,那么调用的只能是算术符重载函数,但是我们这里定义的算数符重载函数有一个陷阱,不知道大家看出来没有?

我提示大家一下,这里的算术符重载需不需要判断拷贝的是不是自己呢?

void process()
{
	data m(10);
	data p = m;
	p = p;
}
这里最后一句,如果算术符可以自己拷贝给自己,代码正常编译和运行都没有问题,但是在某些情况下会出现很多意想不到的情况。大家可以跟着我的思路来:

	data& operator=(const data& d){
		if(this == &d)       /* check whether it is self-copy action */
			return *this;

		if(number)
			free(value);
		number = d.get_number();
		value = (char*)malloc(d.get_number());
		memmove(value, d.get_point(), d.get_number());
		return *this;
	
	}
如果上面的代码没有判断复制的对象是不是自己,那么我们发现实际上value的数据实际上已经free掉了。那么此时重新分配内存,拷贝的数据只有天知道是什么数据。原来value指向的内存空间就存在了很大的不确定性,这就是算术符重载的陷阱。


【后记: 自此用汇编看C++系列全部结束,下面我们将开始数据结构和算法的讨论,欢迎关注】


分享到:
评论

相关推荐

    C++程序设计(谭浩强完整版)

    C++程序设计,谭浩强编著,清华...后来,又把运算符的重载、引用、虚函数等功能加入到C++中,使C++的功能日趋完善。 当前用得较为广泛的C++有:VC++ (Visual C Plus Plus)、 BC++(Borland C Plus Plus)、AT&T C++等

    C++大学教程,一本适合初学者的入门教材(part1)

    第1章 计算机与C++编程简介 1.1 简介 1.2 什么是计算机 1.3 计算机组成 1.4 操作系统的变革 I.5 个人计算、分布式计算与客户/a匠务器计算 l. 6 机器语言、汇编语言和高级语言 1.7 C语言与C++的历史 1.8 C++...

    Visual C++ 2005入门经典--源代码及课后练习答案

    他曾在IBM工作多年,能使用多种语言进行编程(在多种机器上使用汇编语言和高级语言),设计和实现了实时闭环工业控制系统。Horton拥有丰富的教学经验(教学内容包括C、C++、Fortran、PL/1、APL等),同时还是机械、加工...

    nasm PC汇编语言 教程

    3.1.3 算术移位. . . . . . . . . . . . . . . . . . . . . . . . . 42 3.1.4 循环移位. . . . . . . . . . . . . . . . . . . . . . . . . 42 3.1.5 简单应用. . . . . . . . . . . . . . . . . . . . . . . . . 43...

    C++大学教程,一本适合初学者的入门教材(part2)

    第1章 计算机与C++编程简介 1.1 简介 1.2 什么是计算机 1.3 计算机组成 1.4 操作系统的变革 I.5 个人计算、分布式计算与客户/a匠务器计算 l. 6 机器语言、汇编语言和高级语言 1.7 C语言与C++的历史 1.8 C++...

    The Art of Assembly Language

    英文版 以下是我从网上所的相关介绍 内容简介 本书以X86系列微机为背景,从简单的Hello程序开始,系统而详细地阐述了X86微机汇编语言...15.4 使用C/C++和HLA编程 15.5 更多信息 附录A ASCII字符集 附录B 80x86指令集

    C++大学教程

    C++大学教程(目录) 第1章 计算机与C++编程简介-------------------------------------------------1 1.1 简介--------------------------------------------------------------1 1.2 什么是计算机--------...

    C#微软培训资料

    7.2 算术操作符和算术表达式.59 7.3 赋值操作符和赋值表达式.64 7.4 关系操作符和关系表达式.65 <<page 2>> page begin==================== 7.5 逻辑操作符和逻辑表达式.68 7.6 位 运 算 .69 7.7 ...

    Delphi5开发人员指南

    2.5.4 算术运算符 21 2.5.5 按位运算符 22 2.5.6 加减运算过程 22 2.6 Object Pascal类型 23 2.6.1 类型的比较 23 2.6.2 字符 24 2.6.3 字符串 24 2.6.4 变体类型 32 2.6.5 Currency 39 2.7 用户自定义类型 39 2.7.1...

    JAVA上百实例源码以及开源项目

    得到RSA密钥对,产生Signature对象,对用私钥对信息(info)签名,用指定算法产生签名对象,用私钥初始化签名对象,将待签名的数据传送给签名对象(须在初始化之后),用公钥验证签名结果,使用公钥初始化签名对象,用于...

    JAVA上百实例源码以及开源项目源代码

    得到RSA密钥对,产生Signature对象,对用私钥对信息(info)签名,用指定算法产生签名对象,用私钥初始化签名对象,将待签名的数据传送给签名对象(须在初始化之后),用公钥验证签名结果,使用公钥初始化签名对象,用于...

Global site tag (gtag.js) - Google Analytics