结论:构造函数确实隐式地返回了一个该类的对象。
或许底层原理并非如此,但对于接触底层不多的用户来说,这样去理解,我想是没什么大问题的。
最近在学习C++类与对象时,看到了“构造函数不返回任何东西”的说法。然而学到异常处理的部分,却又看到了“throw classname();”这样的语句,这让我非常纳闷。按理说,throw一个函数,应该等价于throw这个函数返回值。但是构造函数classname()不是没有返回值吗?那这里到底throw了个啥?
在好奇心的驱使下,我百度了一圈,发现普遍共识还是构造函数不返回任何东西。然而鉴于“classname obj=classname();”和“throw classname();”这样的写法确实能通过编译,我这个没接触过底层的人还是更愿意相信,构造函数是返回了某些东西的,尽管官方没有承认。
那么它到底返回了什么内容呢?是一个对象吗?还是一个对象的引用?我决定自己动手测一测。(看到个别说法是返回this指针,这是不可能的。如果返回this指针,那么“classname obj=classname();”这样的语句就无法通过编译,因为不能把指针转换为对象)
上测试代码:
#include <iostream>
using namespace std;
class A {
public:
//这是构造函数
A(void) {
cout<<"An A object is created.\n"<<endl;
i=12;
}
const char *thrown(void) {
return "An A is thrown.\n";
}
int i;
} ;
//作为对比,这是一个确定返回对象的函数
A obj(void) {
A obj;
return obj;
}
//作为对比,这是一个确定返回对象引用的函数
A &quo(void) {
static A obj;
return obj;
}
int main(void) {
//cout<<++A().i<<endl;
//cout<<++obj().i<<endl;
//上面两行编译时均会报错:将临时量作为左值
cout<<++quo().i<<endl;//只有返回对象引用的函数可在调用的同时操作成员
//这说明构造函数没有返回对象的引用
try {
//下面两行中保留任意一行,均会执行catch(A obj),说明构造函数确实返回了一个对象
//throw obj();
throw A();
} catch(A obj) {
cout<<obj.thrown()<<endl;
}
//然而构造函数和返回对象的函数,sizeof值却不同
//cout<<sizeof(obj())<<endl;
//cout<<sizeof(A())<<endl;
/*后来发现取sizeof没有任何意义,因为sizeof的过程中根本没有调用函数,
其测得的并不是实际返回值所占空间*/
return 0;
}
测试思路很简单:
1.如果构造函数返回对象的引用,那么应当可以在调用构造函数的同时,将其成员作为左值进行操作,因为C++只允许函数返回静态或全局量的引用,这导致可以在调用这种函数的同时,将其作为左值。
2.如果构造函数返回一个对象,那么throw一个构造函数,和throw一个确定返回对象的自定义函数,catch的结果应该是一样的。
3.如果构造函数真的返回一个对象,那么对构造函数取sizeof,和对一个确定返回对象的自定义函数取sizeof,结果应该是一样的。注:此步作废。原因:一开始对sizeof的原理不了解,以为sizeof一个函数时,会调用这个函数,然后测量其返回内容所占的空间。后来注意到,取sizeof这一步中,程序没有输出“An A object is created.”这行内容,说明在sizeof的过程中,传入的函数根本被没有被调用,也就不可能执行任何return。百度到的内容也确实印证了这一点,即对于一个函数,sizeof不会调用函数本身,而是直接检查函数声明。这样一来,这一步就失去了意义,因为sizeof所测的并不是函数实际返回的内容。
测试结果:
1.不能将构造函数(的成员)作为左值,说明其没有返回对象引用。
2.throw一个构造函数,确实可以catch到一个对象,甚至可以调用其成员函数,这说明构造函数返回了一个对象。
3.对构造函数和确定返回对象的自定义函数分别取sizeof,前者结果为1,后者结果为4,不一致,说明构造函数返回的不是对象,2不成立。注:作废,理由同上。(顺带一提,sizeof(void)就是1。估计构造函数在底层确实近似于void型,因此被指为“不返回任何东西”)
至此,得出结论:构造函数确实隐式地返回了一个该类的对象。或许底层原理并非如此,但对于接触底层不多的用户来说,这样去理解,我想是没什么大问题的。