首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C++ >

关于无名对象与临时对象解决思路

2012-03-07 
关于无名对象与临时对象#includeiostream.hclassX{intcpublic:X(int)X(X&)~X()}X::X(intt){cout

关于无名对象与临时对象
#include   <iostream.h>

class   X
{
int   c;
public:
X(int);
X(X&);
~X();
};

X::X(int   t)
{
cout < < "construct   normal: " < <t < <endl;
c   =   t;
}

X::X(X&   t)
{
cout < < "construct   copy: " < <t.c < <endl;
c   =   t.c;
}

X::~X()
{
cout < < "destory: " < <this-> c < <endl;;
}

X   f(X   t)
{
      X   temp(5);
      return   temp;      
}

void   main()
{
X   a(1);    
X   b   =   f(X(2));
a   =   f(a);
}
输出结果为:
construct   normal:1
construct   normal:2
construct   normal:5
construct   copy:5
destory:5
destory:2
construct   copy:1
construct   normal:5
construct   copy:5
destory:5
destory:1
destory:5
destory:5
destory:5

本来我的分析是:
X   a(1);     调用构造函数X::X(int   t)输出construct   normal:1
X   b   =   f(X(2));
这句按理说是:
1,先调用X::X(int   t)构造一个无名对象,然后调用X::X(X&   t)用实参初始化形参.不过书上说:对于X   k   =   X(1);这种情况,C++将其看作X   k   =   1,省略创建无名对象一步.按照这种说法的话,这里会调用X::X(int   t)直接构造形参.
2,调用X::X(int   t)构造temp局部对象,返回局部对象时,调用X::X(X&   t)用temp初始化临时对象,析构temp局部对象,析构形参对象;
3,返回主函数后调用X::X(X&   t)用临时对象初始化b,析构临时对象.
a   =   f(a);
这句按理说是:
1,调用X::X(X&   t)用a初始化函数形参;
2,调用X::X(int   t)构造temp局部对象,返回局部对象时,调用X::X(X&   t)用temp初始化临时对象,析构temp局部对象,析构形参对象;
3,返回主函数后将临时对象赋值给a,然后析构临时对象.
最后以构造顺序相反的顺序析构主函数中的对象,本来是无名对象,对象b,对象a;因为无名对象没有真正构造,所以只有对象b,对象a.

按照上面的分析,输出语句应该是:
construct   normal:1
construct   normal:2
construct   normal:5
construct   copy:5
destory:5
destory:2
construct   copy:5
destory:5
construct   copy:1
construct   normal:5
construct   copy:5
destory:5
destory:1
destory:5
destory:5
destory:5
比显示结果多了两条:
construct   copy:5
destory:5
即少了用临时对象初始化对象b和临时对象的析构,为什么?
我看的是清华大学出版社钱能的 <C++程序设计教程> ,根据书上讲的自己对这个程序的分析.

[解决办法]
看 <exceptional C++> item 42
[解决办法]
因为2,3点是相关的

"第二次,用临时对象初始化X b "

此时是赋值行为,不会调用拷贝构造函数,
我说了,调用拷贝函数会生成对象, 赋值不等于调用拷贝函数

通俗点说:
记用局部对象temp初始化临时对象为 T

X b = f(); 是给T起个名字 "b "

X b;
b = f(); 是把T的值赋给b

两者都会调用拷贝函数初始化临时对象,临时对象都会析构
所以只执行了一次拷贝函数和一次析构函数
记住,这对临时对象的创建和析构


"那么总共调用了两次拷贝构造函数(第一次:用局部对象temp初始化临时对象,第二次,用临时对象初始化X b),也调用了两次析构函数(第一次:局部对象temp被析构;第二次:临时对象被析构)。 "

修改一下你的说法:

"那么总共调用了一次拷贝构造函数(第一次:用局部对象temp初始化临时对象(创建对象),第二次,把临时对象赋值X b(赋值)),调用了两次析构函数(第一次:局部对象temp被析构(临时对象无关,只是你 X temp(5); 才有这次析构);第二次:临时对象被析构(分两种情况,当b与临时对象为同一体,临时对象的生存周期就为b的周期;当不是同一体,临时对象的周期到下一句结束))。 "

完全正确,
要注意的是 X b = f(); 时b和临时对象是同一体了,该临时对象的析构就相当于b被析构

X b;
b = f(); b和临时对象的析构完全不相干

由于存在这两种情况,所以把你弄混了,你把mian函数改为
void main()
{
X a(1);
X b(1);
b= f(X(2));
a = f(a);
}
吧,应该会得出你想要的结果

经鉴定,你是把拷贝函数和赋值弄混了, 拷贝函数可以说是构造函数的一种




PS:最后一次回复,我已经写得很明白了,再不明白我也没办法

热点排行