现在的位置: 首页 > 综合 > 正文

临时对象实验

2014年01月11日 ⁄ 综合 ⁄ 共 1394字 ⁄ 字号 评论关闭
#ifndef FATHER_H
#define FATHER_H
#include"iostream"
#include<string>
using namespace std;
class father{
public:
	father(std::string  name1) : name(name1){
		cout << "new "  << name << endl;
	}
	father(father & f) : name(f.name) {
		cout << "copy " << f.name << endl;
	}
	virtual ~ father(){
	cout << "delete " << name << endl;
	};
//private:
	std::string name;
};
#endif
#include"father.h"
#include"iostream"
using namespace std;

father f(){
	father f("lisi");
	cout << " hanshu" << endl;
	return f;
}

int main()
{

	father &f1 = father("zhangsan");
	cout << "hehe" << endl;
	cout << f1.get() << endl;

	cout << "------------------------------------" << endl;

	father & s = f();
	cout << " new s" << endl;
	s.name = "wangwu";
	return 0;
}

1、可见语句father &f1 = father("zhangsan");是先生成一个临时对象,然后在调用复制构造函数来初始化f1的,而且这个语句结束,临时对象就自动析构了;

2、调用f()函数来初始化s就不一样:先是在f()函数里面构造了一个father对象,即father f("lisi");但是这个对象并没有return给一个临时的函数返回对象,而是直接赋值给s了,调用的是复制构造函数。这很奇怪。因为father f("lisi");是在函数堆栈区的,当函数结束以后,整个堆栈都是pop出来了,为什么还可以用这个堆栈的对象来初始化s呢?据说这个编译器的优化,但具体为什么如此,我还不懂。

注:问题得以解决,其实编译器优化了,father f("lisi");这个对象是函数堆栈对象,是不可能在函数结束以后存在的。只是编译器在ruturn f;的时候,省略了中间的函数返回临时对象的创建,而是直接赋值给mian()函数里面的s引用了。就好像把s作为函数的临时返回对象了一样。

其实可以再做一个实验,仅仅写一个f();的无用语句,你会发现结果也会有new lisi和copy lisi以及两个delete lisi的。说明这个copy lisi的输出是return时候做的,并不是复制语句中做的,只是在直接赋值给一个对象的时候,编译器优化了中间的步骤而已。

3、s是一个引用,这个引用指向的是一个函数返回的临时对象,当这条语句结束的时候,临时对象会自动析构,按道理应该这个引用无效了,但程序显示并非如此,因为调用了复制构造函数来初始化一个father对象,然后使引用s指向它。这也是编译器奇怪的一点?

注:问题得以解决:在C++之父Bjarne Stroustrup的《The C++ Programming Language》的P89的第九行明确指出:“这种保存引用初始式的临时对象将一直存在,直到这个引用的作用域结束”。

抱歉!评论已关闭.