这个问题来源于一道 C++考试题,要求阅读代码写出输出,代码如下:
#include <iostream>
#include <iomanip>
using namespace std;
class sample {
private:
int x;
public:
sample(int val = 0)
{
x = val;
cout << "构造" << x << endl;
}
sample(const sample &obj)
{
x = obj.x;
cout << "拷贝构造" << x << endl;
}
~sample()
{
cout << "析构" << x << endl;
}
void operator++()
{
x++;
}
friend sample operator+(const sample &a, const sample &b)
{
sample tmp;
tmp.x = a.x + b.x;
return tmp;
}
};
void foo(sample i);
int main()
{
sample s1, s2(1);
foo(s1);
foo(2);
cin.get();
return 0;
}
void foo(sample i)
{
static sample s3 = i + 1;
++s3;
}
问题主要集中在foo函数中
static sample s3 = i + 1;
这一行。当执行到foo(s1)时,我认为函数中关于 s3 的这一句执行顺序是这样的:
- 表达式 i+1 中 i 与 1 类型不匹配,由于 sample 的构造函数重载之一 sample(int val=0)没有 explicit 参数,并且 sample 类对+的重载实现要求+的操作数为两个 sample 对象,故编译器使用该构造函数重载将 1 转换为一个临时 sample 对象,这里输出“构造 1 ”
- 执行 i 与由 1 转换来的临时对象的加法。在加法函数中声明局部 sample 对象 tmp,输出“构造 0 ”。然后在加法重载函数返回时,由于返回值类项为 sample,因此新建一个临时 sample 对象并将 tmp 的值用于初始化这个临时 sample 对象,输出“拷贝构造 1 ”,此后,局部变量 tmp 被回收,输出“析构 1 ”。
- 加法重载函数将上一步中最后生成的临时对象返回到调用处,s3 使用该临时对象初始化,输出“拷贝构造 1 ”。
- 最后这一行代码中为了类型转换而生成的临时对象被销毁,输出“析构 1 ”。
我使用 Visual Studio 2017 编译,Debug x86 编译预设编译运行来检验我的设想,实际输出如下:
构造 1
构造 0
拷贝构造 1
析构 1
析构 1
实际输出和我的设想不同之处在于,输出中没有上述 3.的输出。但是问题在于,进行单步调试后,我观察到在这句代码执行完毕进入++s3时,s3 对象确实已经被创建了,那么 s3 对象是用什么样的方式创建的呢?因为无论如何要创建一个新对象一定要调用某个构造函数,但是我没有能得到任何 s3 构造时产生的输出。
请问 s3 对象是以怎样的方式被构造的呢?感激不尽!