大家好,new和delete的用法相信很多的網友都不是很明白,包括c語言delete函數用法也是一樣,不過沒有關系,接下來就來為大家分享關于new和delete的用法和c語言delete函數用法的一些知識點,大家可以關注收藏,免得下次來找不到哦,下面我們開始吧!
new style使用方法
很簡單。首先,需要下載并安裝newstyle軟件,在電腦上打開軟件后就可以開始使用了。接著,可以根據自己的需求選擇不同的功能,例如制作海報、PPT等等。除此之外,還可以根據自己的喜好進行樣式和字體的選擇,制作出個性化的作品。最后,完成之后可以保存或者分享到社交平臺上,以便自己和他人欣賞和使用。總之,簡單易懂,只需要簡單的幾步就能制作出精美的作品。
C++ new和delete是如何調用構造函數和析構函數的
在C++中,你也許經常使用new和delete來動態申請和釋放內存,但你可曾想過以下問題呢?
new和delete是函數嗎?
new[]和delete[]又是什么?什么時候用它們?
你知道operatornew和operatordelete嗎?
為什么new[]出來的數組有時可以用delete釋放有時又不行?
…
如果你對這些問題都有疑問的話,不妨看看我這篇文章。
new和delete到底是什么?
如果找工作的同學看一些面試的書,我相信都會遇到這樣的題:sizeof不是函數,然后舉出一堆的理由來證明sizeof不是函數。在這里,和sizeof類似,new和delete也不是函數,它們都是C++定義的關鍵字,通過特定的語法可以組成表達式。和sizeof不同的是,sizeof在編譯時候就可以確定其返回值,new和delete背后的機制則比較復雜。
繼續往下之前,請你想想你認為new應該要做些什么?也許你第一反應是,new不就和C語言中的malloc函數一樣嘛,就用來動態申請空間的。你答對了一半,看看下面語句:
string*ps=newstring("helloworld");
你就可以看出new和malloc還是有點不同的,malloc申請完空間之后不會對內存進行必要的初始化,而new可以。所以newexpression背后要做的事情不是你想象的那么簡單。在我用實例來解釋new背后的機制之前,你需要知道operatornew和operatordelete是什么玩意。
operatornew和operatordelete
這兩個其實是C++語言標準庫的庫函數,原型分別如下:
void*operatornew(size_t);//allocateanobject
void*operatordelete(void*);//freeanobject
void*operatornew[](size_t);//allocateanarray
void*operatordelete[](void*);//freeanarray
后面兩個你可以先不看,后面再介紹。前面兩個均是C++標準庫函數,你可能會覺得這是函數嗎?請不要懷疑,這就是函數!C++Primer一書上說這不是重載new和delete表達式(如operator=就是重載=操作符),因為new和delete是不允許重載的。但我還沒搞清楚為什么要用operatornew和operatordelete來命名,比較費解。我們只要知道它們的意思就可以了,這兩個函數和C語言中的malloc和free函數有點像了,都是用來申請和釋放內存的,并且operatornew申請內存之后不對內存進行初始化,直接返回申請內存的指針。
我們可以直接在我們的程序中使用這幾個函數。
new和delete背后機制
知道上面兩個函數之后,我們用一個實例來解釋new和delete背后的機制:
我們不用簡單的C++內置類型來舉例,使用復雜一點的類類型,定義一個類A:
classA
{
public:
A(intv):var(v)
{
fopen_s(&file,"test","r");
}
~A()
{
fclose(file);
}
private:
intvar;
FILE*file;
};
很簡單,類A中有兩個私有成員,有一個構造函數和一個析構函數,構造函數中初始化私有變量var以及打開一個文件,析構函數關閉打開的文件。
我們使用
classA*pA=newA(10);
來創建一個類的對象,返回其指針pA。如下圖所示new背后完成的工作:
簡單總結一下:
首先需要調用上面提到的operatornew標準庫函數,傳入的參數為classA的大小,這里為8個字節,至于為什么是8個字節,你可以看看《深入C++對象模型》一書,這里不做多解釋。這樣函數返回的是分配內存的起始地址,這里假設是0x007da290。
上面分配的內存是未初始化的,也是未類型化的,第二步就在這一塊原始的內存上對類對象進行初始化,調用的是相應的構造函數,這里是調用A:A(10);這個函數,從圖中也可以看到對這塊申請的內存進行了初始化,var=10,file指向打開的文件。
最后一步就是返回新分配并構造好的對象的指針,這里pA就指向0x007da290這塊內存,pA的類型為類A對象的指針。
所有這三步,你都可以通過反匯編找到相應的匯編代碼,在這里我就不列出了。
好了,那么delete都干了什么呢?還是接著上面的例子,如果這時想釋放掉申請的類的對象怎么辦?當然我們可以使用下面的語句來完成:
deletepA;
delete所做的事情如下圖所示:
delete就做了兩件事情:
調用pA指向對象的析構函數,對打開的文件進行關閉。
通過上面提到的標準庫函數operatordelete來釋放該對象的內存,傳入函數的參數為pA的值,也就是0x007d290。
好了,解釋完了new和delete背后所做的事情了,是不是覺得也很簡單?不就多了一個構造函數和析構函數的調用嘛。
如何申請和釋放一個數組?
我們經常要用到動態分配一個數組,也許是這樣的:
string*psa=newstring[10];//arrayof10emptystrings
int*pia=newint[10];//arrayof10uninitializedints
上面在申請一個數組時都用到了new[]這個表達式來完成,按照我們上面講到的new和delete知識,第一個數組是string類型,分配了保存對象的內存空間之后,將調用string類型的默認構造函數依次初始化數組中每個元素;第二個是申請具有內置類型的數組,分配了存儲10個int對象的內存空間,但并沒有初始化。
如果我們想釋放空間了,可以用下面兩條語句:
delete[]psa;
delete[]pia;
都用到delete[]表達式,注意這地方的[]一般情況下不能漏掉!我們也可以想象這兩個語句分別干了什么:第一個對10個string對象分別調用析構函數,然后再釋放掉為對象分配的所有內存空間;第二個因為是內置類型不存在析構函數,直接釋放為10個int型分配的所有內存空間。
這里對于第一種情況就有一個問題了:我們如何知道psa指向對象的數組的大小?怎么知道調用幾次析構函數?
這個問題直接導致我們需要在new[]一個對象數組時,需要保存數組的維度,C++的做法是在分配數組空間時多分配了4個字節的大小,專門保存數組的大小,在delete[]時就可以取出這個保存的數,就知道了需要調用析構函數多少次了。
還是用圖來說明比較清楚,我們定義了一個類A,但不具體描述類的內容,這個類中有顯示的構造函數、析構函數等。那么當我們調用
classA*pAa=newA[3];
時需要做的事情如下:
從這個圖中我們可以看到申請時在數組對象的上面還多分配了4個字節用來保存數組的大小,但是最終返回的是對象數組的指針,而不是所有分配空間的起始地址。
這樣的話,釋放就很簡單了:
delete[]pAa;
這里要注意的兩點是:
調用析構函數的次數是從數組對象指針前面的4個字節中取出;
傳入operatordelete[]函數的參數不是數組對象的指針pAa,而是pAa的值減4。
為什么new/delete、new[]/delete[]要配對使用?
其實說了這么多,還沒到我寫這篇文章的最原始意圖。從上面解釋的你應該懂了new/delete、new[]/delete[]的工作原理了,因為它們之間有差別,所以需要配對使用。但偏偏問題不是這么簡單,這也是我遇到的問題,如下這段代碼:
int*pia=newint[10];
delete[]pia;
這肯定是沒問題的,但如果把delete[]pia;換成deletepia;的話,會出問題嗎?
這就涉及到上面一節沒提到的問題了。上面我提到了在new[]時多分配4個字節的緣由,因為析構時需要知道數組的大小,但如果不調用析構函數呢(如內置類型,這里的int數組)?我們在new[]時就沒必要多分配那4個字節,delete[]時直接到第二步釋放為int數組分配的空間。如果這里使用deletepia;那么將會調用operatordelete函數,傳入的參數是分配給數組的起始地址,所做的事情就是釋放掉這塊內存空間。不存在問題的。
這里說的使用new[]用delete來釋放對象的提前是:對象的類型是內置類型或者是無自定義的析構函數的類類型!
我們看看如果是帶有自定義析構函數的類類型,用new[]來創建類對象數組,而用delete來釋放會發生什么?用上面的例子來說明:
classA*pAa=newclassA[3];
deletepAa;
那么deletepAa;做了兩件事:
調用一次pAa指向的對象的析構函數;
調用operatordelete(pAa);釋放內存。
顯然,這里只對數組的第一個類對象調用了析構函數,后面的兩個對象均沒調用析構函數,如果類對象中申請了大量的內存需要在析構函數中釋放,而你卻在銷毀數組對象時少調用了析構函數,這會造成內存泄漏。
上面的問題你如果說沒關系的話,那么第二點就是致命的了!直接釋放pAa指向的內存空間,這個總是會造成嚴重的段錯誤,程序必然會奔潰!因為分配的空間的起始地址是pAa指向的地方減去4個字節的地方。你應該傳入參數設為那個地址!
同理,你可以分析如果使用new來分配,用delete[]來釋放會出現什么問題?是不是總會導致程序錯誤?
總的來說,記住一點即可:new/delete、new[]/delete[]要配套使用總是沒錯的!
https://www.cnblogs.com/hazir/p/new_and_delete.html
delete和shift的區別
區別就是兩者意思是不一樣的,delete在鍵盤上是表示刪除,shift在鍵盤上是表示轉換。
delete中文意思是n.刪除鍵
Thisscriptwillpromptyoutoeitherdeletetheexistingindexorcreateanewindex.這個腳本將會提示您要么刪除現存的索引,要么創建一個新的索引。
shift中文意思是n.改變,轉變;輪班工作時間;輪班工作的人;(計算機鍵盤上的)Shift鍵;(計算機)移位;
C++ 如果類中有一個指針數據成員,而我沒有用new。析構函數要不要delete
C++無論何種數據,是否要delete關鍵看其空間是否使用new分配的。
1,函數沖定義的局部變量指針,單純是一個局部變量是不用delete;
2,C++如果類中有一個指針數據成員,而沒有用new,析構函數也是不用delete的;在類或函數中,int*,char*這些只要不是new的,也同樣不用釋放,系統會自動把他們占的內存釋放掉,只有new的才會手動的去delete原理:int*,char*,這些定義是局部變量,存在于棧上,比如int*p;p在棧上,而且p的值也是棧的一個地址。但是當int*p=newint;這時候,p這個變量是在棧上的。但是p的值是一個地址,這個地址是堆上的一個地址。如果不deletep;那么,這個地址會一直被占用著,不能被其他的對象所使用,所以我們用完這個地址,要把這個地址釋放掉。因此棧的空間會自動釋放,而堆里的空間必須手動釋放。
c語言new怎么用
new的用法
開辟單變量地址空間
使用new運算符時必須已知數據類型,new運算符會向系統堆區申請足夠的存儲空間,如果申請成功,就返回該內存塊的首地址,如果申請不成功,則返回零值。
new運算符返回的是一個指向所分配類型變量(對象)的指針。對所創建的變量或對象,都是通過該指針來間接操作的,而動態創建的對象本身沒有標識符名。
一般使用格式:
格式1:指針變量名=new類型標識符;
格式2:指針變量名=new類型標識符(初始值);
格式3:指針變量名=new類型標識符[內存單元個數];
說明:格式1和格式2都是申請分配某一數據類型所占字節數的內存空間;但是格式2在內存分配成功后,同時將一初值存放到該內存單元中;而格式3可同時分配若干個內存單元,相當于形成一個動態數組。例如:
1)newint;//開辟一個存放整數的存儲空間,返回一個指向該存儲空間的地址。int*a=newint即為將一個int類型的地址賦值給整型指針a
2)int*a=newint(5)作用同上,但是同時將整數空間賦值為5
2.開辟數組空間
對于數組進行動態分配的格式為:
指針變量名=new類型名[下標表達式];
delete[]指向該數組的指針變量名;
兩式中的方括號是非常重要的,兩者必須配對使用,如果delete語句中少了方括號,因編譯器認為該指針是指向數組第一個元素的指針,會產生回收不徹底的問題(只回收了第一個元素所占空間),加了方括號后就轉化為指向數組的指針,回收整個數組。
delete[]的方括號中不需要填數組元素數,系統自知。即使寫了,編譯器也忽略。
請注意“下標表達式”不必是常量表達式,即它的值不必在編譯時確定,可以在運行時確定。
一維:int*a=newint[100];//開辟一個大小為100的整型數組空間
二維:int**a=newint[5][6]
三維及其以上:依此類推.
一般用法:new類型(初值)
關于new和delete的用法,c語言delete函數用法的介紹到此結束,希望對大家有所幫助。