user-0 提问: 对析构函数的盲点

回复:
user: user-0
content: 引用 13 楼 heroesjun 的回复:[quote=引用 7 楼 U201212366 的回复:] /////.h///////////////// class test { public: 	test(); 	test(char *); 	bool read(void **); 	char * buffer; }; //////.cpp///////////// #include "stdio.h" #include "studybv.h" #include <string.h>   test::test() { 	buffer = NULL; }  test::test(char *p) { 	buffer = p; }  bool test::read( void ** q ) { 	*q = buffer; 	if (*q == NULL) 	{ 		return false; 	} 	return true; }  void main() { 	void *p = NULL; 	char *x = new char[4]; 	char *a = "abc"; 	if(1) 	{ 		test T(a); 			     		if (T.read(&p)) 		{ 			printf("%s",p); 		} 		strcpy(x, (char *)p); 	} 	printf("%s",p); 	printf("%s",x); 	delete []x; } ////////////////////////////// 这是我做的测试用的小程序，为什么结果是“abcabcabc” 第二个printf("%s",p); 不应该因为出了作用域而失效吗  打印p的时候，已经出了T对象的作用域， 所以它会被析构掉，但T类中的buffer指向的是在T对象外部的字符串常量，即main函数中的a字符串“abc”， 这个字符串在main中一直存在，所以p能打印出来。[/quote] 恍然大悟  谢谢

user: user-0
content: 引用 12 楼 aqiu348503 的回复:[quote=引用 7 楼 U201212366 的回复:] /////.h///////////////// class test { public: 	test(); 	test(char *); 	bool read(void **); 	char * buffer; }; //////.cpp///////////// #include "stdio.h" #include "studybv.h" #include <string.h>   test::test() { 	buffer = NULL; }  test::test(char *p) { 	buffer = p; }  bool test::read( void ** q ) { 	*q = buffer; 	if (*q == NULL) 	{ 		return false; 	} 	return true; }  void main() { 	void *p = NULL; 	char *x = new char[4]; 	char *a = "abc"; 	if(1) 	{ 		test T(a); 			     		if (T.read(&p)) 		{ 			printf("%s",p); 		} 		strcpy(x, (char *)p); 	} 	printf("%s",p); 	printf("%s",x); 	delete []x; } ////////////////////////////// 这是我做的测试用的小程序，为什么结果是“abcabcabc” 第二个printf("%s",p); 不应该因为出了作用域而失效吗 你printf的p和x都没出main作用域啊，出了作用域访问就会编译出错的还怎么打印结果[/quote] 是的 可是我的问题是为什么会有结果

user: user-0
content: 引用 11 楼 zhao4zhong1 的回复:生、死 构造、析构 new、delete malloc、free {、}  你说的我知道一点点，可是我的问题是我没有动态创建，需不需要我手动释放，因为F5调试的时候检测到了内存泄露

user: user-1
content: pixData和OpenFilePath所指的空间是动态分配的，还是指向外部数据块，如果是动态分配的话，需要用析构delete掉，myfileheader不需要处理，对象析构的时候会自动释放它。另外如果class没有定义析构函数，那么只有在class内带有member object(或是class自己的base class)拥有析构函数的情况下，编译器才会自动合成一个来，否则析构函数会被视为不需要，也就不需要被合成。但还是建议你不管你的类需不需要，你都应该定义一个析构函数，并声明为virtual，因为如果该类的使用者定义一个子类，非virtual的析构函数有可能导致内存泄露。

user: user-2
content: 理解和讨论之前请先学会如何观察！  计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构……  对学习编程者的忠告： 多用小脑和手，少用大脑、眼睛和嘴，会更快地学会编程！ 眼过千遍不如手过一遍！ 书看千行不如手敲一行！ 手敲千行不如单步一行！ 单步源代码千行不如单步Debug版对应汇编一行！ 单步Debug版对应汇编千行不如单步Release版对应汇编一行！  单步类的实例“构造”或“复制”或“作为函数参数”或“作为函数返回值返回”或“参加各种运算”或“退出作用域”的语句对应的汇编代码几步后，就会来到该类的“构造函数”或“复制构造函数”或“运算符重载”或“析构函数”对应的C/C++源代码处。  VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化，这样过一遍不就啥都明白了吗。 对VC来说，所谓‘调试时’就是编译连接通过以后，按F10或F11键单步执行一步以后的时候，或者在某行按F9设了断点后按F5执行停在该断点处的时候。 （Turbo C或Borland C用Turbo Debugger调试,Linux或Unix下用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。）

user: user-3
content: 在构造时候用了new，那么析构时候就要delete掉

user: user-0
content: 因为我这是动态链接库的导出类，外面的主进程会给我提供相应的参数，在外面可以动态分配内存，而我只需要使数据放到动态分配的内存空间里就行了，因为我内部主要完成的是对结构体对象成员的赋值和获取目标文件相应数据的指针，对于如何转出，我又迷茫了，因为我采用的是void **的方式

user: user-4
content: 个人意见， 强烈建议区分"堆栈".  不需要析构函数就不写或者用~XXXX() = default; 指针指向成员或者结构体? 那为什么不用new?

user: user-1
content: 引用 7 楼 U201212366 的回复://///.h///////////////// class test { public: 	test(); 	test(char *); 	bool read(void **); 	char * buffer; }; //////.cpp///////////// #include "stdio.h" #include "studybv.h" #include <string.h>   test::test() { 	buffer = NULL; }  test::test(char *p) { 	buffer = p; }  bool test::read( void ** q ) { 	*q = buffer; 	if (*q == NULL) 	{ 		return false; 	} 	return true; }  void main() { 	void *p = NULL; 	char *x = new char[4]; 	char *a = "abc"; 	if(1) 	{ 		test T(a); 			     		if (T.read(&p)) 		{ 			printf("%s",p); 		} 		strcpy(x, (char *)p); 	} 	printf("%s",p); 	printf("%s",x); 	delete []x; } ////////////////////////////// 这是我做的测试用的小程序，为什么结果是“abcabcabc” 第二个printf("%s",p); 不应该因为出了作用域而失效吗  打印p的时候，已经出了T对象的作用域， 所以它会被析构掉，但T类中的buffer指向的是在T对象外部的字符串常量，即main函数中的a字符串“abc”， 这个字符串在main中一直存在，所以p能打印出来。

user: user-5
content: 引用 7 楼 U201212366 的回复://///.h///////////////// class test { public: 	test(); 	test(char *); 	bool read(void **); 	char * buffer; }; //////.cpp///////////// #include "stdio.h" #include "studybv.h" #include <string.h>   test::test() { 	buffer = NULL; }  test::test(char *p) { 	buffer = p; }  bool test::read( void ** q ) { 	*q = buffer; 	if (*q == NULL) 	{ 		return false; 	} 	return true; }  void main() { 	void *p = NULL; 	char *x = new char[4]; 	char *a = "abc"; 	if(1) 	{ 		test T(a); 			     		if (T.read(&p)) 		{ 			printf("%s",p); 		} 		strcpy(x, (char *)p); 	} 	printf("%s",p); 	printf("%s",x); 	delete []x; } ////////////////////////////// 这是我做的测试用的小程序，为什么结果是“abcabcabc” 第二个printf("%s",p); 不应该因为出了作用域而失效吗 你printf的p和x都没出main作用域啊，出了作用域访问就会编译出错的还怎么打印结果

user: user-2
content: 生、死 构造、析构 new、delete malloc、free {、}

user: user-0
content: 我要的就是地址，这个是作为fopen的参数的

user: user-6
content: 在实例对象时成员分配内存空间，如果你不给openfile成员使用new来初始化分配具体的空间大小，那它所占的空间只是一个地址大小而已（除非你用数组形式），所以既然要用new,也就要析构delete

user: user-1
content: 栈区存放该类的对象，但对象本身有指针变量，指针变量指向的空间有可能是在对象存在的生命期中动态分配的，所以析构函数里必须释放这些指针。

user: user-0
content: /////.h///////////////// class test { public: 	test(); 	test(char *); 	bool read(void **); 	char * buffer; }; //////.cpp///////////// #include "stdio.h" #include "studybv.h" #include <string.h>   test::test() { 	buffer = NULL; }  test::test(char *p) { 	buffer = p; }  bool test::read( void ** q ) { 	*q = buffer; 	if (*q == NULL) 	{ 		return false; 	} 	return true; }  void main() { 	void *p = NULL; 	char *x = new char[4]; 	char *a = "abc"; 	if(1) 	{ 		test T(a); 			     		if (T.read(&p)) 		{ 			printf("%s",p); 		} 		strcpy(x, (char *)p); 	} 	printf("%s",p); 	printf("%s",x); 	delete []x; } ////////////////////////////// 这是我做的测试用的小程序，为什么结果是“abcabcabc” 第二个printf("%s",p); 不应该因为出了作用域而失效吗

user: user-0
content: 因为我之前想的是既然我要用到这个类的对象，那么在栈区已经有了相应空间，我就没必要再去new一个到堆区离了，不知道这种想法是否正确。