Java和C++通過(guò)new創(chuàng)建的對(duì)象有何區(qū)別?
前言
本文我們不去談int、float、char等基本數(shù)據(jù)類型,而是用一般的類來(lái)說(shuō)明。因?yàn)镴ava中可以直接通過(guò) int varName 的方式來(lái)定義和使用一個(gè)基本類型的變量,但對(duì)于其它一般類型的對(duì)象,必須使用 new 來(lái)創(chuàng)建。
因此,為了更一般性地分析,體現(xiàn)兩種語(yǔ)言創(chuàng)建對(duì)象的差異,我們用自定義的類 Student 進(jìn)行說(shuō)明,以下內(nèi)容均針對(duì)一般的類而言。
Java
在 Java 中,我們可以通過(guò)如下方式定義變量:
Student s; //定義標(biāo)識(shí)符s,沒(méi)有實(shí)際空間 Student s = new Student(); //定義s,并綁定到新創(chuàng)建的對(duì)象
JVM在進(jìn)行內(nèi)存管理時(shí),首先會(huì)在棧中給dog分配一個(gè)空間,當(dāng)new Dog();后會(huì)在堆中開辟對(duì)象的實(shí)際空間,然后將dog指向堆中的空間,這樣我們就可以方法對(duì)象的成員變量了。
圖3 Java創(chuàng)建對(duì)象方式的內(nèi)存分配
c++
在C++中,變量也可以同上來(lái)定義,但含義不同:
Student s; //定義標(biāo)識(shí)符s,并在棧中申請(qǐng)空間 Student* s = new Student(); //定義s,并在堆中申請(qǐng)空間,過(guò)后需手動(dòng)釋放內(nèi)存
這兩種方式在C++中都能完成對(duì)象的創(chuàng)建,但是在內(nèi)存中的處理卻完全不同。
對(duì)于第一種方式而言,dog是被存儲(chǔ)在棧中的,占用的大小是Dog類中成員變量占用內(nèi)存的和,此處不包括成員方法,因?yàn)槌蓡T方法是存放在公共存儲(chǔ)區(qū)以便所有該類的對(duì)象都可以訪問(wèn)的。
圖1 C++創(chuàng)建對(duì)象方式1的內(nèi)存分配
對(duì)于第二種方式則不同,該方式使用了指針,在定義*p時(shí)在棧中開辟一個(gè)4字節(jié)的空間,new Dog()時(shí)在堆中開辟一塊空間,然后將該空間的首地址賦值給*p,這樣,通過(guò)*p就可以找到對(duì)象在堆中的任何成員方法了。
圖2 C++創(chuàng)建對(duì)象方式2的內(nèi)存分配
區(qū)別總結(jié)
兩種語(yǔ)言里都含有 new 操作符,但它們的含義大不相同,這與它倆的變量管理方式有關(guān)。
在 Java 中,只有當(dāng)你使用 new 操作符時(shí),才會(huì)真正在內(nèi)存中申請(qǐng)一塊空間,創(chuàng)建一個(gè)新對(duì)象,并將該對(duì)象綁定到你所定義的變量名上。其它情況下,要么是將已有對(duì)象綁定到某個(gè)變量名上,要么就是定義的變量名是個(gè)空引用,沒(méi)有綁定任何對(duì)象。
也就是說(shuō),定義變量名只是創(chuàng)建了一個(gè)新的標(biāo)識(shí)符,跟創(chuàng)建對(duì)象沒(méi)有關(guān)系,創(chuàng)建對(duì)象必須通過(guò) new 來(lái)完成,只有創(chuàng)建對(duì)象時(shí)才會(huì)申請(qǐng)內(nèi)存空間。
但在 C++ 中,當(dāng)你定義了一個(gè)變量 s 時(shí),即使你沒(méi)有給它賦值,也意味著你不但創(chuàng)建了一個(gè)新的標(biāo)識(shí)符,同時(shí)還在棧中申請(qǐng)了對(duì)應(yīng)的內(nèi)存空間。
因此,C++ 中定義的變量名不僅僅是個(gè)標(biāo)識(shí)符,還自動(dòng)關(guān)聯(lián)著棧中的一塊內(nèi)存空間。
而 C++ 中的 new 操作符表示的是在堆中申請(qǐng)內(nèi)存,因?yàn)闂V械膬?nèi)存在運(yùn)行時(shí)期大小是固定且有限的,因此需要?jiǎng)討B(tài)內(nèi)存分配的時(shí)候就需要用 new 來(lái)實(shí)現(xiàn)。這類似于 C 里面的 malloc 函數(shù),只不過(guò) new 操作符還封裝了其它的操作。
總結(jié)而言,Java 中的變量名僅僅是一個(gè)用于引用內(nèi)存中實(shí)際對(duì)象的標(biāo)識(shí)符,如果你沒(méi)給它關(guān)聯(lián)對(duì)象,它就為空引用。而 C++ 中的變量名(非指針類型),雖然也是標(biāo)識(shí)符,但卻始終關(guān)聯(lián)著實(shí)際的內(nèi)存空間,當(dāng)我們看到一個(gè)變量(非指針類型)時(shí),就知道它代表著一塊實(shí)際的內(nèi)存空間。
總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)腳本之家的支持。
相關(guān)文章
SpringBoot整合EasyExcel實(shí)現(xiàn)復(fù)雜Excel表格的導(dǎo)入導(dǎo)出
這篇文章主要為大家詳細(xì)介紹了SpringBoot如何整合EasyExcel實(shí)現(xiàn)復(fù)雜Excel表格的導(dǎo)入導(dǎo)出功能,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以參考下2023-11-11Java 關(guān)于時(shí)間復(fù)雜度和空間復(fù)雜度的深度刨析
算法復(fù)雜度分為時(shí)間復(fù)雜度和空間復(fù)雜度。其作用: 時(shí)間復(fù)雜度是度量算法執(zhí)行的時(shí)間長(zhǎng)短;而空間復(fù)雜度是度量算法所需存儲(chǔ)空間的大小2021-11-11IDEA+maven+SpringBoot+JPA+Thymeleaf實(shí)現(xiàn)Crud及分頁(yè)
這篇文章主要介紹了不需要電腦任何操作基于IDEA + maven + SpringBoot + JPA + Thymeleaf實(shí)現(xiàn)CRUD及分頁(yè),需要的朋友可以參考下2018-03-03詳解Java多線程編程中互斥鎖ReentrantLock類的用法
Java多線程并發(fā)的程序中使用互斥鎖有synchronized和ReentrantLock兩種方式,這里我們來(lái)詳解Java多線程編程中互斥鎖ReentrantLock類的用法:2016-07-07Java數(shù)據(jù)結(jié)構(gòu)篇之實(shí)現(xiàn)二叉搜索樹的核心方法
二叉搜索樹是一種常用的數(shù)據(jù)結(jié)構(gòu),它是一棵二叉樹,且每個(gè)節(jié)點(diǎn)的值都大于其左子樹中任何節(jié)點(diǎn)的值,而小于其右子樹中任何節(jié)點(diǎn)的值,這篇文章主要給大家介紹了關(guān)于Java數(shù)據(jù)結(jié)構(gòu)篇之實(shí)現(xiàn)二叉搜索樹的核心方法,需要的朋友可以參考下2023-12-12