C++
				和
				C#/java
				有很多区别,其中最大的区别当数对内存的管理。
				
						
						
						
				
		
		
				C++
				中,类的使用者决定了类的实例内存会如何分配,分配在堆上还是栈上。我们先看一段例子程序:
				
						
						
				
		
		
				
						 
				
		
		
				#include
				
						"stdio.h"
				
		
		
				
						 
				
		
		
				class
				 Demo{
		
		
				public
				:
		
		
				
						    
						int i;
		
		
				
						    
						char* objName;
		
		
				
						    Demo(){
		
		
				
						        objName = "Default object.";
		
		
				
						        printf("%s, objName = %s\r\n", "Enter Demo default ctor. method.", objName);
		
		
				
						        
						
						
				
		
		
				
						        i = 1000;
		
		
				
						    }
		
		
				
						 
				
		
		
				
						    Demo(int ival, char* name){
		
		
				
						        printf("%s,i = %d, objName = %s\r\n", "Enter Demo(int ival) ctor method", ival, name);
		
		
				
						        i = ival;
		
		
				
						        objName = name;
		
		
				
						    }
		
		
				
						 
				
		
		
				
						    Demo(const Demo& d){
		
		
				
						        printf("%s\r\n", "Enter Demo copy ctor method.");
		
		
				
						        i = d.i;
		
		
				
						        objName = "copied d";
		
		
				
						    }
		
		
				
						 
				
		
		
				
						    ~Demo(){
		
		
				
						        printf("%s, i = %d, objName = %s\r\n", "Enter Demo dector. method" , i, objName);
		
		
				
						    }
		
		
				};
		
		
				
						 
				
		
		
				Demo& testMethod0(){
		
		
				
						    printf("%s\r\n", "Enter testMethod0.");
		
		
				
						    Demo d(0, "d in testMethod0");
		
		
				
						    printf("%s\r\n", "Exit testMethod0.");
		
		
				
						    
						return d;
		
		
				}
		
		
				
						 
				
		
		
				Demo testMethod1(){
		
		
				
						    printf("%s\r\n", "Enter testMethod1.");
		
		
				
						    Demo d(1, "d in testMethod1");
		
		
				
						    printf("%s\r\n", "Exit testMethod1.");
		
		
				
						    
						return d;
		
		
				}
		
		
				
						 
				
		
		
				Demo* testMethod2(){
		
		
				
						    printf("%s\r\n", "Enter testMethod2.");
		
		
				
						    Demo *d = new Demo(2, "d in testMethod2");
		
		
				
						    printf("%s\r\n", "Exit testMethod2.");
		
		
				
						    
						return d;
		
		
				}
		
		
				
						 
				
		
		
				int
				 main(int argc, _TCHAR* argv[])
		
		
				{
		
		
				
						    Demo d;
		
		
				
						    d = testMethod1();
		
		
				
						 
				
		
		
				
						    Demo& d1 = testMethod0();
		
		
				
						 
				
		
		
				
						    Demo d2(999, "d1");
		
		
				
						 
				
		
		
				
						    Demo* d3 = testMethod2();
		
		
				
						 
				
		
		
				
						    printf("d.i = %d\r\n", d.i);
		
		
				
						    printf("d1.i = %d\r\n", d1.i);
		
		
				
						    printf("d2.i = %d\r\n", d2.i);
		
		
				
						    printf("d3.i = %d\r\n", d3->i);
		
		
				
						 
				
		
		
				
						    
						delete d3;
		
		
				
						    
						return 0;
		
		
				}
		
		
				
						 
				
		
		
				Output
				:
				
						
						
				
		
		
				Enter Demo default ctor. method., objName = Default object.
		
		
				Enter testMethod1.
		
		
				Enter Demo(int ival) ctor method,i = 1, objName = d in testMethod1
		
		
				Exit testMethod1.
		
		
				Enter Demo copy ctor method.
		
		
				Enter Demo dector. method, i = 1, objName = d in testMethod1
		
		
				Enter Demo dector. method, i = 1, objName = copied d
		
		
				Enter testMethod0.
		
		
				Enter Demo(int ival) ctor method,i = 0, objName = d in testMethod0
		
		
				Exit testMethod0.
		
		
				Enter Demo dector. method, i = 0, objName = d in testMethod0
		
		
				Enter Demo(int ival) ctor method,i = 999, objName = d1
		
		
				Enter testMethod2
		
		
				Enter Demo(int ival) ctor method,i = 2, objName = d in testMethod2
		
		
				Exit testMethod2.
		
		
				d.i = 1
		
		
				d1.i = -2
		
		
				d2.i = 999
		
		
				d3.i = 2
		
		
				Enter Demo dector. method, i = 2, objName = d in testMethod2
		
		
				Enter Demo dector. method, i = 999, objName = d1
		
		
				Enter Demo dector. method, i = 1, objName = copied d
				
						
						
				
		
		
				
						 
				
		
		
				与
				C#
				不同,在
				C++
				中,对象声明的时候就已经执行了构造函数,比如上面例子的
				main
				函数中的第一行,
				Demo d
				,从屏幕上的输出来看,这个时候
				Demo class
				的默认构造函数会被调用。
				
						
						
				
		
		
				接下来的一行代码调用,引出了很有趣的情况,当然也隐藏着不小的问题。这行代码造成了一次构造函数调用,一次拷贝构造函数调用和两次析构函数调用。让我们来具体分析一下:第一次调用构造函数很容易理解,因为在
				testMethod1
				中我们声明了
				Demo d(0)
				,退出
				testMethod1
				,函数的返回值要赋值给变量
				d2
				,这个时候,
				d2
				被拷贝构造函数重新构造了一次。接着
				testMethod1
				中构造的局部变量被析构,然后,居然拷贝构造函数构造的对象也被析构?等等,看完所有输出,我们发现,
				objName = copied d
				的对象被析构两次,而
				objName = Default obj
				的对象被构造出之后没有被析构,这里隐藏了很严重的问题,有可能导致内存泄漏、句柄不能被正确关闭等等。另外,拷贝构造函数的执行可能导致潜在的效率问题,考虑一个包含巨大矩阵的对象,
				copy
				这个对象会怎么样?
				
						
						
				
		
		
				
						 
				
		
		
				接下来的一行代码,
				testMethod0
				返回一个对象的引用,当然不会导致拷贝构造函数被调用,但是,这样也是有问题的,在函数中声明的局部变量在函数执行完成的时候会被析构,那么直接返回局部变量就可能会出现问题。
				testMethod0
				退出以后,他内部的
				Demo
				对象就会自动析构,外面对它的引用当然也无法指向正确的对象了,所以后面程序打印
				d.i
				的时候,输出了一个莫名其妙的
				-2
				。
				
						
						
				
		
		
				
						 
				
		
		
				效率最好的方法当数返回指针了,它不会导致对象复制,如果使用得当,也不会导致内存泄漏或者句柄泄漏。
				testMethod2
				演示了这种情况,当然,你需要手工删除在
				testMethod2
				中创建的对象。