C++中假如創建類A的對象a。
可以這樣做:
(1): A a;
(2): A *p=new A;
這兩種方法的異同:
A a; 這樣的對象的內存分配在棧上,超出作用域(比如在函數fun中創建的a對象,在函數結束後,就超出了作用域) 就調用析構函數將對象銷燬。
A *p=new A;這種的內存是分配在堆上的,分配之後到程序結束前一直存在,除非你用delete p;這樣纔會調用析構函數將對象消亡.
示例:
#include <iostream.h>
class tree{
int height;
public:
tree(int Height){
height=Height;
}
~tree(){cout<<"****";}
friend ostream& operator <<(ostream &os,const tree*t){
return os<<"tree height is:"<<t->height<<endl;
}
};
int main(){
tree *T= new tree(40);
cout<<T;
//delete T;
//tree t(40);
//cout<<&t;
return 0;
}
運行結果:
tree height is:40
Press any key to continue
如果取消對delete T; 語句的註釋,運行結果爲:
tree height is:40
****Press any key to continue
如果mian()爲:
int main(){
//tree *T= new tree(40);
//cout<<T;
//delete T;
tree t(40);
cout<<&t;
return 0;
}
運行結果爲:
tree height is:40
****Press any key to continue
以下引用相關辨析:
A a; 這種寫法完全是C語言的遺留問題,還要爲值和引用分別寫拷貝構造函數,有些繁瑣了,java和.net就沒這種情況了,所有的對象都是引用類型,而且運用原形模式實現ICloneable接口可以代替拷貝構造函數,其實完全可以用指針或者引用來處理問題.
java和.net因爲內存垃圾回收機制纔敢這麼做,C++在局部函數結束後直接把局部對象全給釋放了,效率高。
而java即使GC也是"建議"進行垃圾收集,收集速度也不敢恭維。
C++和java 創建對象的異同(轉):
創建對象:C++和Java的異同
C++ |
Java |
類定義:
Class User {...}; |
類定義:
Class User {...} |
對象構造: (1)
User u(...); 對象構造: (2) User * p = new User(...);
|
對象構造:
User q = new User(...); |
在標號爲(1)的構造函數調用中,我們可以把u本身當作一個User對象。這個構造函數調用填充由u對象所佔據的內存區域,如下圖(a)部分所示。
標號爲(2)的構造函數調用創建了一小塊內存區域,其中存儲了p的值(一個內存地址),然後填充一個較大的內存區域,賦值符右邊所創建的User對象就存儲在這塊內存中。p所指向的內存地址就是User對象存儲位置。如下圖(b)部分所示
Java的構造函數調用也保留一個內存位置存儲q的值,並填充一塊內存保存User對象。在這種情況下,爲q的值所保留的內存地址保存了User對象引用,如下圖(C)部分所示。
我們可以把q中存儲的對象引用看成是一個僞指針(一個內存僞地址),之所以說它是僞指針,是因爲我們不能像C++指針那樣對它進行解引用。如果由於內存管理的需要,JVM決定把這個User對象移動到內存中的一個不同位置,q所保存的對象引用仍然能夠找到這個對象。反之,如果p所指向的對象轉移到內存中的不同位置,那麼p的值需要在程序的控制下進行顯示的修改。