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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

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

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

解析一:

new創(chuàng)建類對象,使用完后需使用delete刪除,跟申請內存類似。所以,new有時候又不太適合,比如在頻繁調用場合,使用局部new類對象就不是個好選擇,使用全局類對象或一個經過初始化的全局類指針似乎更加高效。

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

下面是自己總結的一些關于new創(chuàng)建類對象特點:

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

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

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

CTest* pTest = new CTest();

delete pTest;

pTest用來接收類對象指針。

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

CTest mTest;

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

2、只定義類指針

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

CTest* pTest = NULL;

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

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

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

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

?

?

解析二:

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

?

復制代碼 代碼如下:


#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ū)別,一個隱式調用,一個顯式調用,兩者都是在進程虛擬地址空間中的棧中分配內存,而第三種使用了new,在堆中分配了內存,而棧中內存的分配和釋放是由系統(tǒng)管理,而堆中內存的分配和釋放必須由程序員手動釋放,所以這就產生一個問題是把對象放在棧中還是放在堆中的問題,這個問題又和堆和棧本身的區(qū)別有關:

?

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

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

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

由上可知,但我們需要的內存很少,你又能確定你到底需要多少內存時,請用棧。而當你需要在運行時才知道你到底需要多少內存時,請用堆。

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

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

?

復制代碼 代碼如下:


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

解析三:

舉個簡單的例子: 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的定義方式有何本質不同?用哪種方式比較好? 最佳答案 p1有系統(tǒng)創(chuàng)建并釋放,你不要擔心會出現(xiàn)內存泄露,但是生命期只有在本區(qū)域的大括號內,出了大括號就沒用了。P2是指針,要自己釋放,用不好很危險,用好了功能強大,因為他可以賦值給全局的變量,一下子從局部變量變成全局變量,還能把對象作為函數(shù)返回值。

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

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

類實現(xiàn)略。

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


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

?

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

一個類的實例化對象所占空間的大小?

?

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

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

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

如果在類中聲明了虛函數(shù)(不管是1個還是多個),那么在實例化對象時,編譯器會自動在對象里安插一個指針指向虛函數(shù)表VTable,在32位機器上,一個對象會增加4個字節(jié)來存儲此指針,它是實現(xiàn)面向對象中多態(tài)的關鍵。而虛函數(shù)本身和其他成員函數(shù)一樣,是不占用對象的空間的。

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

#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擴充為2個字,但是對象b為什么沒擴充為1個字呢?大家?guī)兔鉀Q
cout<<sizeof(c)<<endl;//result=8??
//對象c實際上只有6字節(jié)有用數(shù)據(jù),但是按照上面第二點編譯器優(yōu)化,編譯器將此擴展為兩個字,即8字節(jié)
cout<<sizeof(d)<<endl;//result=8??
}??

綜上所述:

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

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

總結

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

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。