日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

c++中类型用new和不用new的区别

發(fā)布時(shí)間:2023/12/18 c/c++ 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 c++中类型用new和不用new的区别 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

解析一:

new創(chuàng)建類對象,使用完后需使用delete刪除,跟申請內(nèi)存類似。所以,new有時(shí)候又不太適合,比如在頻繁調(diào)用場合,使用局部new類對象就不是個(gè)好選擇,使用全局類對象或一個(gè)經(jīng)過初始化的全局類指針?biāo)坪醺痈咝А?/p>

一、new創(chuàng)建類對象與不new區(qū)別

下面是自己總結(jié)的一些關(guān)于new創(chuàng)建類對象特點(diǎn):

  • new創(chuàng)建類對象需要指針接收,一處初始化,多處使用
  • new創(chuàng)建類對象使用完需delete銷毀
  • new創(chuàng)建對象直接使用堆空間,而局部不用new定義類對象則使用棧空間
  • new對象指針用途廣泛,比如作為函數(shù)返回值、函數(shù)參數(shù)等
  • 頻繁調(diào)用場合并不適合new,就像new申請和釋放內(nèi)存一樣

二、new創(chuàng)建類對象實(shí)例

1、new創(chuàng)建類對象例子:

CTest* pTest = new CTest();

delete pTest;

pTest用來接收類對象指針。

不用new,直接使用類定義申明:

CTest mTest;

此種創(chuàng)建方式,使用完后不需要手動(dòng)釋放,該類析構(gòu)函數(shù)會(huì)自動(dòng)執(zhí)行。而new申請的對象,則只有調(diào)用到delete時(shí)再會(huì)執(zhí)行析構(gòu)函數(shù),如果程序退出而沒有執(zhí)行delete則會(huì)造成內(nèi)存泄漏。

2、只定義類指針

這跟不用new申明對象有很大區(qū)別,類指針可以先行定義,但類指針只是個(gè)通用指針,在new之前并為該類對象分配任何內(nèi)存空間。比如:

CTest* pTest = NULL;

但使用普通方式創(chuàng)建的類對象,在創(chuàng)建之初就已經(jīng)分配了內(nèi)存空間。而類指針,如果未經(jīng)過

對象初始化,則不需要delete釋放。

3、new對象指針作為函數(shù)參數(shù)和返回值

下面是天緣隨手寫一個(gè)例子,不太嚴(yán)謹(jǐn)。主要示意一下類指針對象作為返回值和參數(shù)使用。

?

?

解析二:

我們都知道C++中有三種創(chuàng)建對象的方法,如下:

?

復(fù)制代碼 代碼如下:


#include <iostream>
using namespace std;

?

class A
{
private:
??? int n;
public:
??? A(int m):n(m)
??? {
??? }
??? ~A(){}
};

int main()
{
??? A a(1);? //棧中分配
??? A b = A(1);? //棧中分配
??? A* c = new A(1);? //堆中分配
  delete c;
??? return 0;
}


第一種和第二種沒什么區(qū)別,一個(gè)隱式調(diào)用,一個(gè)顯式調(diào)用,兩者都是在進(jìn)程虛擬地址空間中的棧中分配內(nèi)存,而第三種使用了new,在堆中分配了內(nèi)存,而棧中內(nèi)存的分配和釋放是由系統(tǒng)管理,而堆中內(nèi)存的分配和釋放必須由程序員手動(dòng)釋放,所以這就產(chǎn)生一個(gè)問題是把對象放在棧中還是放在堆中的問題,這個(gè)問題又和堆和棧本身的區(qū)別有關(guān):

?

這里面有幾個(gè)問題:
1.堆和棧最大可分配的內(nèi)存的大小
2.堆和棧的內(nèi)存管理方式
3.堆和棧的分配效率

首先針對第一個(gè)問題,一般來說對于一個(gè)進(jìn)程棧的大小遠(yuǎn)遠(yuǎn)小于堆的大小,在linux中,你可以使用ulimit -s (單位kb)來查看一個(gè)進(jìn)程棧的最大可分配大小,一般來說不超過8M,有的甚至不超過2M,不過這個(gè)可以設(shè)置,而對于堆你會(huì)發(fā)現(xiàn),針對一個(gè)進(jìn)程堆的最大可分配的大小在G的數(shù)量級(jí)上,不同系統(tǒng)可能不一樣,比如32位系統(tǒng)最大不超過2G,而64為系統(tǒng)最大不超過4G,所以當(dāng)你需要一個(gè)分配的大小的內(nèi)存時(shí),請用new,即用堆。

其次針對第二個(gè)問題,棧是系統(tǒng)數(shù)據(jù)結(jié)構(gòu),對于進(jìn)程/線程是唯一的,它的分配與釋放由操作系統(tǒng)來維護(hù),不需要開發(fā)者來管理。在執(zhí)行函數(shù)時(shí),函數(shù)內(nèi)局部變量的存儲(chǔ)單元都可以在棧上創(chuàng)建,函數(shù)執(zhí)行結(jié)束時(shí),這些存儲(chǔ)單元會(huì)被自動(dòng)釋放。棧內(nèi)存分配運(yùn)算內(nèi)置于處理器的指令集中,效率很高,不同的操作系統(tǒng)對棧都有一定的限制。 堆上的內(nèi)存分配,亦稱動(dòng)態(tài)內(nèi)存分配。程序在運(yùn)行的期間用malloc申請的內(nèi)存,這部分內(nèi)存由程序員自己負(fù)責(zé)管理,其生存期由開發(fā)者決定:在何時(shí)分配,分配多少,并在何時(shí)用free來釋放該內(nèi)存。這是唯一可以由開發(fā)者參與管理的內(nèi)存。使用的好壞直接決定系統(tǒng)的性能和穩(wěn)定。

由上可知,但我們需要的內(nèi)存很少,你又能確定你到底需要多少內(nèi)存時(shí),請用棧。而當(dāng)你需要在運(yùn)行時(shí)才知道你到底需要多少內(nèi)存時(shí),請用堆。

最后針對第三個(gè)問題,棧是機(jī)器系統(tǒng)提供的數(shù)據(jù)結(jié)構(gòu),計(jì)算機(jī)會(huì)在底層對棧提供支持:分配專門的寄存器存放棧的地址,壓棧出棧都有專門的指令執(zhí)行,這就決定了棧的效率 比較高。堆則是C/C++函數(shù)庫提供的,它的機(jī)制是很復(fù)雜的,例如為了分配一塊內(nèi)存,庫函數(shù)會(huì)按照一定的算法(具體的算法可以參考數(shù)據(jù)結(jié)構(gòu)/操作系統(tǒng))在 堆內(nèi)存中搜索可用的足夠大小的空間,如果沒有足夠大小的空間(可能是由于內(nèi)存碎片太多),就有可能調(diào)用系統(tǒng)功能去增加程序數(shù)據(jù)段的內(nèi)存空間,這樣就有機(jī)會(huì) 分 到足夠大小的內(nèi)存,然后進(jìn)行返回。顯然,堆的效率比棧要低得多。

由上可知,能用棧則用棧。

?

復(fù)制代碼 代碼如下:


#include <stdio.h>
#include <stdlib.h>?
void main()
{
?int n,*p,i,j,m;
?printf("本程序可對任意個(gè)整數(shù)排序;\n");
?printf("請輸入整數(shù)的總個(gè)數(shù): ");
?scanf("%d",&n);
?p=(int *)calloc(n,sizeof(int));??? //運(yùn)行時(shí)決定內(nèi)存分配大小
?if(p==0)?? {
? printf("分配失敗!\n");?
? exit(1);?
?}

解析三:

舉個(gè)簡單的例子: class Point { private: int x; int y; public: void Set(int a,int b) { x=a; y=b; } void Print() { cout<<"("<<x<<","<<y<<")"<<endl; } }; void main() { Point p1; Point *p2=new Point(); p1.Set(1,2); p2->Set(4,5); p1.Print(); p2->Print(); delete p2; } 對象p1,p2的定義方式有何本質(zhì)不同?用哪種方式比較好? 最佳答案 p1有系統(tǒng)創(chuàng)建并釋放,你不要擔(dān)心會(huì)出現(xiàn)內(nèi)存泄露,但是生命期只有在本區(qū)域的大括號(hào)內(nèi),出了大括號(hào)就沒用了。P2是指針,要自己釋放,用不好很危險(xiǎn),用好了功能強(qiáng)大,因?yàn)樗梢再x值給全局的變量,一下子從局部變量變成全局變量,還能把對象作為函數(shù)返回值。

------------------------------------------------

先定義一個(gè)類:
class A
{
public:
A();
virtual ~A();
...
...
};

類實(shí)現(xiàn)略。

用的時(shí)候:
A a;
a.成員函數(shù);
a.成員變量;
a 就是一個(gè)對象。


也可以這樣用:
A *a = new A;
a->成員函數(shù);
a->成員變量;
最后別忘了銷毀對象: delete[] a;

?

-----------------------------------------------

一個(gè)類的實(shí)例化對象所占空間的大小?

?

注意不要說類的大小,是類的對象的大小.

首先,類的大小是什么?確切的說,類只是一個(gè)類型定義,它是沒有大小可言的。
用sizeof運(yùn)算符對一個(gè)類型名操作,得到的是具有該類型實(shí)體的大小。
如果
Class A;
A obj;
那么sizeof(A)==sizeof(obj)
那么sizeof(A)的大小和成員的大小總和是什么關(guān)系呢,很簡單,一個(gè)對象的大小大于等于所有非靜態(tài)成員大小的總和。
為什么是大于等于而不是正好相等呢?超出的部分主要有以下兩方面:
1) C++對象模型本身
對于具有虛函數(shù)的類型來說,需要有一個(gè)方法為它的實(shí)體提供類型信息(RTTI)和虛函數(shù)入口,常見的方法是建立一個(gè)虛函數(shù)入口表,這個(gè)表可為相同類型的對象共享,因此對象中需要有一個(gè)指向虛函數(shù)表的指針,此外,為了支持RTTI,許多編譯器都把該類型信息放在虛函數(shù)表中。但是,是否必須采用這種實(shí)現(xiàn)方法,C++標(biāo)準(zhǔn)沒有規(guī)定,但是這幾戶是主流編譯器均采用的一種方案。
2) 編譯器優(yōu)化
因?yàn)閷τ诖蠖鄶?shù)CPU來說,CPU字長的整數(shù)倍操作起來更快,因此對于這些成員加起來如果不夠這個(gè)整數(shù)倍,有可能編譯器會(huì)插入多余的內(nèi)容湊足這個(gè)整數(shù)倍,此外,有時(shí)候相鄰的成員之間也有可能因?yàn)檫@個(gè)目的被插入空白,這個(gè)叫做“補(bǔ)齊”(padding)。所以,C++標(biāo)準(zhǔn)緊緊規(guī)定成員的排列按照類定義的順序,但是不要求在存儲(chǔ)器中是緊密排列的。
基于上述兩點(diǎn),可以說用sizeof對類名操作,得到的結(jié)果是該類的對象在存儲(chǔ)器中所占據(jù)的字節(jié)大小,由于靜態(tài)成員變量不在對象中存儲(chǔ),因此這個(gè)結(jié)果等于各非靜態(tài)數(shù)據(jù)成員(不包括成員函數(shù))的總和加上編譯器額外增加的字節(jié)。后者依賴于不同的編譯器實(shí)現(xiàn),C++標(biāo)準(zhǔn)對此不做任何保證。

C++標(biāo)準(zhǔn)規(guī)定類的大小不為0,空類的大小為1,當(dāng)類不包含虛函數(shù)和非靜態(tài)數(shù)據(jù)成員時(shí),其對象大小也為1。

如果在類中聲明了虛函數(shù)(不管是1個(gè)還是多個(gè)),那么在實(shí)例化對象時(shí),編譯器會(huì)自動(dòng)在對象里安插一個(gè)指針指向虛函數(shù)表VTable,在32位機(jī)器上,一個(gè)對象會(huì)增加4個(gè)字節(jié)來存儲(chǔ)此指針,它是實(shí)現(xiàn)面向?qū)ο笾卸鄳B(tài)的關(guān)鍵。而虛函數(shù)本身和其他成員函數(shù)一樣,是不占用對象的空間的。

我們來看下面一個(gè)例子:(此例子在Visual C++編譯器中編譯運(yùn)行)

#include <iostream>
using namespace std;
class?? A??
{??
};??
class?? B??
{??
char?? ch;??
void?? func()??
{??
}??
};??
class?? C??
{??
char?? ch1;??? //占用1字節(jié)
char?? ch2;?? //占用1字節(jié)
virtual?? void?? func()??
{??
}??
};??
class?? D??
{??
int?? in;??
virtual?? void?? func()??
{??
}??
};??
void?? main()??
{??
A?? a;
B?? b;
C?? c;
D?? d;
cout<<sizeof(a)<<endl;//result=1??
cout<<sizeof(b)<<endl;//result=1??//對象c擴(kuò)充為2個(gè)字,但是對象b為什么沒擴(kuò)充為1個(gè)字呢?大家?guī)兔鉀Q
cout<<sizeof(c)<<endl;//result=8??
//對象c實(shí)際上只有6字節(jié)有用數(shù)據(jù),但是按照上面第二點(diǎn)編譯器優(yōu)化,編譯器將此擴(kuò)展為兩個(gè)字,即8字節(jié)
cout<<sizeof(d)<<endl;//result=8??
}??

綜上所述:

一個(gè)類中,虛函數(shù)、成員函數(shù)(包括靜態(tài)與非靜態(tài))和靜態(tài)數(shù)據(jù)成員都是不占用類對象的存儲(chǔ)空間的。

對象大小=?? vptr(可能不止一個(gè))?? +?? 所有非靜態(tài)數(shù)據(jù)成員大小?? +?? Aligin字節(jié)大小(依賴于不同的編譯器)

總結(jié)

以上是生活随笔為你收集整理的c++中类型用new和不用new的区别的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。