class CTest { public: CTest(const char* str) { strcpy(name,str); cout<< "constructor for " << name <<endl; } CTest(const CTest& arg) { strcpy(name,arg.name); cout << "copy constructor for " << name <<endl; } ~CTest() { cout << "destructor for " << name << endl; } private: char name[20]; }; CTest foo(CTest arg) { CTest localObject("local"); static CTest staticObject("static"); return localObject; } CTest g_globalobj("global"); int main() { CTest a("a"); CTest* b = new CTest("b"); CTest c = foo(a) delete b; }
为何输出是:
constructor for global constructor for a constructor for b copy constructor for a constructor for local constructor for static destructor for a destructor for b destructor for local destructor for a destructor for static destructor for global
解决方案
20
CTest g_globalobj(“global”); //1
int main()
{
CTest a(“a”);
CTest* b = new CTest(“b”);
CTest c = foo(a)
delete b;
}
按顺序
先定义全局变量 g_globalobj 调用对应构造函数CTest(const char* str) 输出constructor for global;
局部变量 a 对应 CTest(const char* str) 输出constructor for a
指针变量 b 对应 CTest(const char* str) 输出constructor for b
接下来的CTest c = foo(a);语句,先调用CTest的构造函数 CTest(const CTest& arg)创建 foo(CTest arg) 的传入参数arg
所以输出 copy constructor for a, 然后运行foo函数里的 CTest localObject(“local”); 输出constructor for local 然后是
static CTest staticObject(“static”); 输出constructor for static; 跳出函数foo 将函数内的局部变量localObject返回
创建c 调用的是 CTest(const CTest& arg) 输出copy constructor for local,原因是跳出了函数foo,所以其内的局部变量CTest localObject会析构 输出 destructor for local 并且传入参数foo(CTest arg) arg也会析构,输出 destructor for a ; 然后跳出函数 delete b输出destructor for b, 然后函数main运行结束,开始析构main内的局部变量a,c以及静态变量staticObject和全局变量g_globalobj; 原因是a 和c 是栈存储,后进先出,所以先析构c 输出destructor for local 然后析构a输出destructor for a
然后是静态变量staticObject 和全局变量g_globalobj的析构,这个原因是全局变量是定义在mian之前,整个程序结束后才析构而静态变量staticObject则是在main结束后就析构, 所以先输出destructor for static然后是destructor for global
认真看会发现 constructor for static 还有copy constructor for local 和destructor for local你没有输出 ,这个是返回值CTest c = foo(a)拷贝到c的过程和函数内局部变量localObject的析构。
这里有个有趣的问题,就是函数CTest foo(CTest arg)的传入参数arg和局部变量localObject的析构顺序
是先析构传入参数arg再析构localObject,而不是多数人想的栈的后进先出,至少从很多编译器看都是这样,至于原因如下:
CTest foo(CTest arg)
{
CTest localObject(“local”);
static CTest staticObject(“static”);
return localObject;
}
原因是函数参数一般处于函数调用者的栈帧上,而函数内部的局部变量处在本函数对应的栈帧上,是位于不同的栈上的,本人通过反汇编查看也是发现传入参数和函数内局部变量的栈是不同的,故函数一结束先清空函数的栈,再清空传入参数的栈。
int main()
{
CTest a(“a”);
CTest* b = new CTest(“b”);
CTest c = foo(a)
delete b;
}
按顺序
先定义全局变量 g_globalobj 调用对应构造函数CTest(const char* str) 输出constructor for global;
局部变量 a 对应 CTest(const char* str) 输出constructor for a
指针变量 b 对应 CTest(const char* str) 输出constructor for b
接下来的CTest c = foo(a);语句,先调用CTest的构造函数 CTest(const CTest& arg)创建 foo(CTest arg) 的传入参数arg
所以输出 copy constructor for a, 然后运行foo函数里的 CTest localObject(“local”); 输出constructor for local 然后是
static CTest staticObject(“static”); 输出constructor for static; 跳出函数foo 将函数内的局部变量localObject返回
创建c 调用的是 CTest(const CTest& arg) 输出copy constructor for local,原因是跳出了函数foo,所以其内的局部变量CTest localObject会析构 输出 destructor for local 并且传入参数foo(CTest arg) arg也会析构,输出 destructor for a ; 然后跳出函数 delete b输出destructor for b, 然后函数main运行结束,开始析构main内的局部变量a,c以及静态变量staticObject和全局变量g_globalobj; 原因是a 和c 是栈存储,后进先出,所以先析构c 输出destructor for local 然后析构a输出destructor for a
然后是静态变量staticObject 和全局变量g_globalobj的析构,这个原因是全局变量是定义在mian之前,整个程序结束后才析构而静态变量staticObject则是在main结束后就析构, 所以先输出destructor for static然后是destructor for global
认真看会发现 constructor for static 还有copy constructor for local 和destructor for local你没有输出 ,这个是返回值CTest c = foo(a)拷贝到c的过程和函数内局部变量localObject的析构。
这里有个有趣的问题,就是函数CTest foo(CTest arg)的传入参数arg和局部变量localObject的析构顺序
是先析构传入参数arg再析构localObject,而不是多数人想的栈的后进先出,至少从很多编译器看都是这样,至于原因如下:
CTest foo(CTest arg)
{
CTest localObject(“local”);
static CTest staticObject(“static”);
return localObject;
}
原因是函数参数一般处于函数调用者的栈帧上,而函数内部的局部变量处在本函数对应的栈帧上,是位于不同的栈上的,本人通过反汇编查看也是发现传入参数和函数内局部变量的栈是不同的,故函数一结束先清空函数的栈,再清空传入参数的栈。