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

对象作为实参传递引起的变化解决办法

2012-03-20 
对象作为实参传递引起的变化Date是类名,date2,date3是对象名date2fun(date3)fun(Date d){Date temptemp

对象作为实参传递引起的变化
Date是类名,date2,date3是对象名
date2=fun(date3);
fun(Date d)
{
  Date temp;
  temp=d;
  return temp;
}
书上说这样就会产生一个匿名对象,但是我不知道匿名对象是什么,也不知道匿名对象怎么产生。还有当对象作为实参传递和用对象赋值时会有什么变化。并且上面这个程序调用构造函数和析构函数的顺序是什么

[解决办法]
fun(date3) 应该是这个会产生一个匿名对象吧 返回了一个Date对象 用来初始化一个匿名的临时对象

接着再用这临时对象 初始化 date2 

调用顺序是这样的
date3 构造
d 构造
temp 构造
匿名对象 构造(返回值) temp 析构 d 析构 
date2 构造
匿名对象析构


[解决办法]
写个类的构造函数,析构函数和拷贝构造函数,用个简单的fun,就能查看了,如果用你的fun,里面还有构造析构,可以用下面的函数跟踪一下
class Date
{
public:
Date()
{
cout<<"默认构造!"<<endl;
}
Date(Date &d)
{
cout<<"拷贝构造!"<<endl;
}
~Date()
{
cout<< "析构!"<<endl;
}


};

int fun(Date d)
{
return 1;



int main(int argc, char *argv[])
{

cout<<"创建对象d:"<<endl;
Date d;

cout<<endl<<"调用函数:"<<endl;
int i = fun(d);

cout<<"函数调用结束!"<<endl<<endl;

system("PAUSE");
return EXIT_SUCCESS;
}

[解决办法]
我认为匿名对象就是无名对象.......
额,上面这句可以说是废话, 举个列子吧, 构造函数分为显示调用和隐式调用。
比如Data MyData; (隐含调用构造函数,创建了一个有名对象。)
再比如Data *p = new Data;(显示调用构造函数,创建了一个无名的对象,然后把指针的地址赋值);
如果你的Data类中有好几个构造函数,
比如:Data(30);//Data(30).m_data;(显示调用构造函数,创建了一个无名对象。可以用这个无名对象来访问其成员变量);
Data::Data(5).m_data;
Data *p = &Data(30);
以上都是构造函数显示调用,创建了无名的对象。

我感觉,参数形参是类的对象,调用的是拷贝构造函数,而不是构造函数。
同时,返回值为类的对象(注意,是值传递,而不是引用或者指针。) 
调用的也是拷贝构造函数,也就是为什么大多数软件公司都要求,传参的时候尽量用对象的引用,而不是直接传递对象,因为拷贝构造函数会造成空间上的浪费。 而传地址则不用担心这些.....(同时还防止死循环,如果一个类的对象给自身赋值,那么调用的是拷贝构造函数。这点不经常发生。我随口一提,感兴趣可以自己查查。)
还有就是,编译器的不同会有区别。
返回值尽量是对象的引用, (注意,此时会造成引用的悬空,所谓引用的悬空是指一个函数结束时,它所创建的类的对象的声明周期就结束,此时那片对象的空间会被析构掉。 当然了,如果那个对象是被用作形参传进去的就不算了,因为它的生命周期在外面的作用域);
返回值是对象的引用还可以用再连续赋值上。 比如重载了<<或>>运算符时, friend ofstream & operator <<(ofstream &stream,类名,&对象名);
它返回一个流的对象,正好可以连续输出......
下面回到你这道题哈....

C/C++ code
date2=fun(date3); //首先Date date2,date3;被创建,是构造函数隐式调用,这是2次构造函数的调用。fun(Date d)       //传值(类的对象),拷贝构造函数调用{  Date temp;     //构造函数隐式调用,有名对象temp被创建。  temp=d;          return temp; //返回值,拷贝构造函数被调用.}                /*                  然后是析构函数被调用,首先是temp,然后按照你创建的顺序依次进行析构函数的调用                 正好和构造函数顺序相反。
[解决办法]
额....昨天回答的问题,今天再上来看看,发现自己说的还是有不足的地方,补充下吧,
仔细想了想, 
类似于
Date date2,date3;
date2 = fun(date3);
因为调用了一个函数,通过它的返回值来给date2赋值, 但是请注意,2个对象并不在一个栈里。
fun()函数栈里,重新创建了一个Date temp, 当return temp时, 会创建一个临时对象,调用拷贝构造函数,
把temp的值拷贝过去(按位拷贝。)date2在main函数栈里, 此时会有些问题。 当一条语句结束时,fun();函数遇见分号时,生命周期就结束了,此时会调用析构函数, 如果要是用指针呢? 既返回一个对象的指针或者引用?又要分两种情况了,
既:
1 Date &date2 = fun(date3);
2 Date *date2 = fun(date3);

第一种情况,是个引用,引用对于我们来说,好像自身就带有'常'属性,(这里的常不是真的常,而是说引用在声明的时候必须初始化,伴随着它初始化的变量或者对象生存或者消亡。) 在vc里,如果返回一个对象给一个引用初始化了,那么就把那个临时变量的生命周期延长,但是gun里不会这样。编译报错。

第二种情况下,VC下,返回的临时变量生命周期不会被延长,即碰见语句结尾分号,就被析构掉了,但是通过指针,依旧可以访问那片地址空间。GUN里依然是报错,不允许这样用。

热点排行