有关无名对象和拷贝构造函数的问题

时间:2021-07-04 19:25:48
下面这个程序:

#include <iostream>
using namespace std;
class X
{
public:
  X(int);
  X(X&);
  ~X();
};

X::X(int s){ cout <<"create a X object with " <<s <<endl; }
X::X(X& x){ cout <<"create a X object from other X object\n"; }
X::~X(){ cout <<"erase a object\n"; }

X f(X x)
{
  cout <<"call a func with para X object\n";
  return x;
}

void main()
{
  X a(1);
  X b=f(X(2));
  a=f(a);
}

运行结果:

create a X object with 1
create a X object with 2
call a func with para X object
create a X object from other X object
erase a object
create a X object from other X object
call a func with para X object
create a X object from other X object
erase a object
erase a object
erase a object
erase a object

我想知道 X b=f(X(2));的执行流程,为什么看起来f(X(2)中的无名对象为f(X x)中的x初始化时并没有调用拷贝构造函数呢?而是直接执行了f(X x)的函数体???

18 个解决方案

#1


进行传值时,并不是先构造x,再将参数赋值过来.应该是先计算该参数,利用他来生成x
f(X(2)):X(2)本身就是一个临时变量, 不会再调用构造函数生成x得.
如果是f(a)的话,就会拷贝构造函数.

我是这么理解的

#2


那第一次调用析构函数也就是第五行的erase a object是对谁进行的析构?

谢谢!!

#3


但是它还是生成了一个X的对象呀,create a X object from other X object这句话不就是说由一个X的对象又生成了另一个X的对象吗?

#4


X b=f(X(2)); f函数的形参X x = X(2)  即 X x(2);
a=f(a);                 X x = X(a)     X x(a);

#5


f(X(2));
X(2)是显式转换的意思,把2转换成X对象。(你的构造函数中必须有x(int),它才能把int进行显式转化,没有的话将会由于无法匹配类型,会造成错误)
X x=X(2);
先把2显式转换成X对象,再初始拷贝化给x

#6


第五行的erase a object是对谁进行的析构?

#7


X(2)是显式转换的意思,把2转换成X对象。--------2不是参数吗,怎么成了对象了?X(2)不是表示要创建一个无名对象吗?

#8


在钱能的<c++程序设计教程>中说到。

Student s=student(“jenny”);
按理说c++ 先调用构造函数创建一个无名对象。再调用拷贝化函数创建对象s.但是是用无名对象拷贝一个对象,拷贝完后无明对象没有用,对于这种情况,C++特别地将它看为
Student s=“jenny”;并且省略创建无名对象这一步。

由此可看出,X(2)省去无名对象的构造。
我觉的楼主大可给它把这步看成显示转换成此种对象。
X x=X(2),等价于X x=2 
只不过它是调用拷贝函数来给它创建。

#9


对不起,说错了!

#10


不客气!!谢谢你!!!


第五行的erase a object是对谁进行的析构?

没人知道吗????哪位大侠知道的话说一下吧,感激不尽那!!!

#11


我晕了

#12


个人理解:
1  X b=f(X(2));首先执行的是创建一个X对象,初始值为2,因此你会先看到create a X object with 2
2  接着执行函数体,因此你会看到call a func with para X object
3  return x;操作是最关键的,首先是调用拷贝构造函数,创建b对象并给b赋值
4  因为x是函数的局部变量,是从堆栈空间分配的,因此函数结束后这个对象要销毁

结论:第5行的erase a object是对b(X(2))中的X(2)这个临时变量的析构

#13


4  因为x是函数的局部变量,是从堆栈空间分配的,因此函数结束后这个对象要销毁

结论:第5行的erase a object是对b(X(2))中的X(2)这个临时变量的析构
--------------x同X(2)不是一个概念吧,这个x是个形参,这个X(2)是个实参,函数结束后,形参x被释放掉,这个x才是临时对象吧,这个X(2)不是临时对象呀,但是,函数执行完后,它也应该被释放掉才对,可是这个地方只有一个erase a object,我总觉得少了一个呢,想破脑袋也想不出到底是哪里理解有误!!

郁闷死我了,后面的章节都看不下去了。。。。。谁来帮帮我呀!!!

#14


要是谁能详细讲下临时对象的存储过程就好了,钱能的书好象讲的是错误的。

学习ing.

#15


没有人知道????还是不屑回答???

#16


首先你要明白一点,如类似下面的代码:
X(2);
系统一样会调用X的构造函数,和析构函数。就是说虽然这行代码
什么都没有做,但是系统还是生成了一个对象,这个对象是没有
名字的,后面的代码无法使用的。这就是所谓的无名对象。

在你的代码中,很显然第5个erase是f(X(2))这里面的这个无名对象
在使用完以后的析构动作。这个你可以给X加一个成员变量m,然后
让m等于构造函数带入的值,析构的时候把它显示出来就可以看到了。

我明白你的疑惑,你无非是想说按照道理X(2)生成的这个临时对象A
应该在传参数的时候将自身复制一份给f这个函数所在的栈空间,所
以按照道理来说应该有一次拷贝构造函数的调用是这样麽?

我觉得也许是这个原因,因为编译器是会有优化动作的,他觉得既然
已经生成了这个X(2)的无名对象,就可以在f函数里面用了,没有必要
再复制一份,所以就优化掉了。

#17


呵呵,楼上的,真是高手啊,不但能回答问题还能看出我的疑惑在哪里,佩服至极!!


等我再好好琢磨琢磨。。。。

#18


mark

#1


进行传值时,并不是先构造x,再将参数赋值过来.应该是先计算该参数,利用他来生成x
f(X(2)):X(2)本身就是一个临时变量, 不会再调用构造函数生成x得.
如果是f(a)的话,就会拷贝构造函数.

我是这么理解的

#2


那第一次调用析构函数也就是第五行的erase a object是对谁进行的析构?

谢谢!!

#3


但是它还是生成了一个X的对象呀,create a X object from other X object这句话不就是说由一个X的对象又生成了另一个X的对象吗?

#4


X b=f(X(2)); f函数的形参X x = X(2)  即 X x(2);
a=f(a);                 X x = X(a)     X x(a);

#5


f(X(2));
X(2)是显式转换的意思,把2转换成X对象。(你的构造函数中必须有x(int),它才能把int进行显式转化,没有的话将会由于无法匹配类型,会造成错误)
X x=X(2);
先把2显式转换成X对象,再初始拷贝化给x

#6


第五行的erase a object是对谁进行的析构?

#7


X(2)是显式转换的意思,把2转换成X对象。--------2不是参数吗,怎么成了对象了?X(2)不是表示要创建一个无名对象吗?

#8


在钱能的<c++程序设计教程>中说到。

Student s=student(“jenny”);
按理说c++ 先调用构造函数创建一个无名对象。再调用拷贝化函数创建对象s.但是是用无名对象拷贝一个对象,拷贝完后无明对象没有用,对于这种情况,C++特别地将它看为
Student s=“jenny”;并且省略创建无名对象这一步。

由此可看出,X(2)省去无名对象的构造。
我觉的楼主大可给它把这步看成显示转换成此种对象。
X x=X(2),等价于X x=2 
只不过它是调用拷贝函数来给它创建。

#9


对不起,说错了!

#10


不客气!!谢谢你!!!


第五行的erase a object是对谁进行的析构?

没人知道吗????哪位大侠知道的话说一下吧,感激不尽那!!!

#11


我晕了

#12


个人理解:
1  X b=f(X(2));首先执行的是创建一个X对象,初始值为2,因此你会先看到create a X object with 2
2  接着执行函数体,因此你会看到call a func with para X object
3  return x;操作是最关键的,首先是调用拷贝构造函数,创建b对象并给b赋值
4  因为x是函数的局部变量,是从堆栈空间分配的,因此函数结束后这个对象要销毁

结论:第5行的erase a object是对b(X(2))中的X(2)这个临时变量的析构

#13


4  因为x是函数的局部变量,是从堆栈空间分配的,因此函数结束后这个对象要销毁

结论:第5行的erase a object是对b(X(2))中的X(2)这个临时变量的析构
--------------x同X(2)不是一个概念吧,这个x是个形参,这个X(2)是个实参,函数结束后,形参x被释放掉,这个x才是临时对象吧,这个X(2)不是临时对象呀,但是,函数执行完后,它也应该被释放掉才对,可是这个地方只有一个erase a object,我总觉得少了一个呢,想破脑袋也想不出到底是哪里理解有误!!

郁闷死我了,后面的章节都看不下去了。。。。。谁来帮帮我呀!!!

#14


要是谁能详细讲下临时对象的存储过程就好了,钱能的书好象讲的是错误的。

学习ing.

#15


没有人知道????还是不屑回答???

#16


首先你要明白一点,如类似下面的代码:
X(2);
系统一样会调用X的构造函数,和析构函数。就是说虽然这行代码
什么都没有做,但是系统还是生成了一个对象,这个对象是没有
名字的,后面的代码无法使用的。这就是所谓的无名对象。

在你的代码中,很显然第5个erase是f(X(2))这里面的这个无名对象
在使用完以后的析构动作。这个你可以给X加一个成员变量m,然后
让m等于构造函数带入的值,析构的时候把它显示出来就可以看到了。

我明白你的疑惑,你无非是想说按照道理X(2)生成的这个临时对象A
应该在传参数的时候将自身复制一份给f这个函数所在的栈空间,所
以按照道理来说应该有一次拷贝构造函数的调用是这样麽?

我觉得也许是这个原因,因为编译器是会有优化动作的,他觉得既然
已经生成了这个X(2)的无名对象,就可以在f函数里面用了,没有必要
再复制一份,所以就优化掉了。

#17


呵呵,楼上的,真是高手啊,不但能回答问题还能看出我的疑惑在哪里,佩服至极!!


等我再好好琢磨琢磨。。。。

#18


mark