成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

C#與C++資源管理方式對陣 GC對比RAII

開發(fā) 后端
本文將對比介紹C#和C++的資源管理方式:GC和RAII。C#通過CLR管理托管內(nèi)存,在C語言中,資源管理則是一個極為繁瑣易錯的工作。

資源管理

在C語言中,資源管理是一個極為繁瑣易錯的工作,大多復(fù)雜的C系統(tǒng)都面臨著內(nèi)存泄露、懸掛指針等問題。這是一方面是由底層語言的特點(diǎn)決定;另一方面也是由于C語言特性相對較少,嚴(yán)重依賴程序員進(jìn)行正確的資源管理,缺乏有效的支持手段。

C#和C++兩門語言的定位不同,它們在資源管理方面采取了兩種截然不同的方式:一為GC,一為RAII。GC讓程序建立在更高的抽象層次上,使資源管理變得更方便,更安全;而RAII則保留了C的底層能力,同時在C++特性的支持下提供了簡單有效的資源管理方式。我們知道C++最激烈的批評往往來自于C社區(qū),而在我看來C程序員可以不接受虛函數(shù),不接受模板,但有什么理由不接受RAII呢?可以說RAII是C++相對C來說幾乎無副作用的明顯進(jìn)步。

下面就從GC開始:

引用代替指針

C#通過CLR管理托管內(nèi)存,用引用抽象代替指針間接操作托管內(nèi)存,讓程序員在更高的層次上安全地使用資源。這使得C#失去了直接管理內(nèi)存的能力,但換來了以下好處:

1.類型安全:在C/C++中可以通過類型轉(zhuǎn)換把整數(shù)或其他類型的指針轉(zhuǎn)換為特定類型的指針,這意味著指針是非類型安全的,必須由程序員來保證指針代表的內(nèi)存空間的合法性。而C#引用可以看作是類型安全的指針,as運(yùn)算符可以保證轉(zhuǎn)換的類型安全性。

2.內(nèi)存整理:創(chuàng)建對象需要從堆中動態(tài)分配連續(xù)的內(nèi)存空間,由于不同對象的內(nèi)存大小是不同的,常見的首次匹配和最優(yōu)匹配堆分配算法都會造成堆中的內(nèi)存碎片問題。碎片的存在使實(shí)際可用內(nèi)存小于物理內(nèi)存,所以應(yīng)盡量減少碎片的產(chǎn)生。一個方向是設(shè)計更好的內(nèi)存分配算法;另一個方向是通過周期性地進(jìn)行內(nèi)存整理調(diào)整優(yōu)化。在C/C++中,由于指針代表了絕對地址,因此不存在通用的內(nèi)存整理算法;而C#屏蔽了指針,通過引用操作對象,就使得內(nèi)存整理成為可能。PS:這并不意味著C/C++內(nèi)存分配就弱于C#,C/C++程序可以為某種類型的對象設(shè)計專用的內(nèi)存分配方式,甚至把對象指定分配到某一物理地址空間,這些都是C#不具備的。

托管和非托管資源

在C#中,資源分為托管資源和非托管資源兩種。GC在回收無用對象資源時,可以自動回收托管資源(比如托管內(nèi)存),但對于非托管資源(比如Socket、文件、數(shù)據(jù)庫連接)必須在程序中顯式釋放。

托管資源的回收首先需要GC識別無用對象,然后回收其資源。一般無用對象是指通過當(dāng)前的系統(tǒng)根對象和調(diào)用堆棧對象不可達(dá)的對象。對象有一個重要的特點(diǎn)導(dǎo)致無用對象判斷的復(fù)雜性:對象間的相互引用!如果沒有相互引用,就可以通過“引用計數(shù)”這種簡單高效的方式實(shí)現(xiàn)無用對象的判斷,并實(shí)現(xiàn)實(shí)時回收。正是由于相互引用的存在導(dǎo)致GC需要設(shè)計更為復(fù)雜的算法,這樣帶來的最大問題在于喪失了資源回收的實(shí)時性,而變成一種不確定的方式。

對于非托管資源的釋放,C#提供了兩種方式:

1.Finalizer:寫法貌似C++的析構(gòu)函數(shù),本質(zhì)上卻相差甚遠(yuǎn)。Finalizer是對象被GC回收之前調(diào)用的終結(jié)器,初衷是在這里釋放非托管資源,但由于GC運(yùn)行時機(jī)的不確定性,通常會導(dǎo)致非托管資源釋放不及時。另外,F(xiàn)inalizer可能還會有意想不到的副作用,比如:被回收的對象已經(jīng)沒有被其他可用對象所引用,但Finalizer內(nèi)部卻把它重新變成可用,這就破壞了GC垃圾收集過程的原子性,增大了GC開銷。

2.Dispose Pattern:C#提供using關(guān)鍵字支持Dispose Pattern進(jìn)行資源釋放。這樣能通過確定的方式釋放非托管資源,而且using結(jié)構(gòu)提供了異常安全性。所以,一般建議采用Dispose Pattern,并在Finalizer中輔以檢查,如果忘記顯式Dispose對象則在Finalizer中釋放資源。

可以說,GC為程序帶來安全方便的同時也付出了不小的代價:一則喪失了托管資源回收的實(shí)時性,這在實(shí)時系統(tǒng)和資源受限系統(tǒng)中是致命的;二則沒有把托管資源和非托管資源的管理統(tǒng)一起來,造成概念割裂。C++的定位之一是底層開發(fā)能力,所以不難理解GC并沒有成為C++的語言特性。雖然我們在C++0x和各種第三方庫都能看到GC的身影,但GC對于C++來講并不是那么重要,至多是一個有益的補(bǔ)充。C++足以傲視C,并和C# GC一較高下的是它的RAII。

棧語義

在介紹RAII之前,讓我們先來看一道C++面試題:“重構(gòu)下面的代碼,在保證正確釋放資源的情況下,去掉多余的try catch”

  1. //C++  
  2. void f(){  
  3.     try{  
  4.         int *ptr = new int(123);  
  5.         …//do something with ptr  
  6.        delete ptr;  
  7.     }  
  8.     catch {  
  9.         delete ptr;  
  10.     }  

代碼中new int在堆上分配內(nèi)存,并通過delete小心翼翼地釋放內(nèi)存。這是典型的C風(fēng)格的C++代碼,雖然用了try、catch等高級語法,但資源管理方式依舊是C。按C++特有的方式可以重構(gòu)成這樣:

  1. //C++資源管理方式  
  2. //定義資源代理類模板  
  3. template 
  4. class Resource{  
  5. public:  
  6.     Resource(T *ptr) { this->ptr = ptr;} //構(gòu)造函數(shù)中初始化資源  
  7.     ~Resource() { delete ptr; } //析構(gòu)函數(shù)中釋放資源  
  8.     T& operator*() { return *ptr; } //重載*運(yùn)算符  
  9.     T* operator->() { return ptr; } //重載->運(yùn)算符  
  10.     //…省略了拷貝構(gòu)造函數(shù)和賦值運(yùn)算符等  
  11. private:  
  12.    T* ptr;  
  13. };  
  14. void f(){  
  15.     Resource r(new int(123));  
  16.     //do something with r  

f函數(shù)中,我們在棧上創(chuàng)建了一個資源模板類Resource的對象r,并通過r來提供服務(wù)。只是這么簡單的一包裝,就省掉了繁瑣易錯的try,catch,不管f內(nèi)部出什么問題,拋什么異常,都能保證r所管理的內(nèi)存資源最終被正確釋放。C++保證一旦離開詞法作用域,在任何情況下都會調(diào)用棧上對象的析構(gòu)函數(shù),這就是所謂的“棧語義”(stack semantics)。事實(shí)上,STL已經(jīng)有auto_ptr這個智能指針類模板,其實(shí)現(xiàn)和上面的Resource類模板類似。

RAII

RAII是resource acquisition is initialization的縮寫,意為“資源獲取即初始化”。它是C++之父Bjarne Stroustrup提出的設(shè)計理念,其核心是把資源和對象的生命周期綁定,對象創(chuàng)建獲取資源,對象銷毀釋放資源。在RAII的指導(dǎo)下,C++把底層的資源管理問題提升到了對象生命周期管理的更高層次。上面的例子,我們把new所獲取的內(nèi)存塊視為資源,把r對象視為資源的代理對象,r應(yīng)負(fù)責(zé)資源的獲取和釋放。在棧語義和操作符重載的支持下,C++的RAII體現(xiàn)出了簡潔、安全、實(shí)時的特點(diǎn):

1.概念簡潔性:讓資源(包括內(nèi)存和非內(nèi)存資源)和對象的生命周期綁定,資源類的設(shè)計者只需用在類定義內(nèi)部處理資源問題,提高了程序的可維護(hù)性

2.類型安全性:通過資源代理對象包裝資源(指針變量),并利用運(yùn)算符重載提供指針運(yùn)算方便使用,但對外暴露類型安全的接口

3.異常安全性:棧語義保證對象析構(gòu)函數(shù)的調(diào)用,提高了程序的健壯性

4.釋放實(shí)時性:和GC相比,RAII達(dá)到了和手動釋放資源一樣的實(shí)時性,因此可以承擔(dān)底層開發(fā)的重任

也許你還在驚訝RAII如此簡單的時候,關(guān)于RAII的主要內(nèi)容已經(jīng)介紹完了。簡單不意味著簡陋,在我看來RAII雖然不像GC一樣,是一套具體的機(jī)制,但它蘊(yùn)含的對象與資源關(guān)系的哲學(xué)深度的理解卻使得我對Bjarne Stroustrup肅然起敬!

最后,不得不提醒RAII的理念固然簡單,不過在具體實(shí)現(xiàn)的時候仍有需要小心的地方。比如對于STL的auto_ptr,可以視為資源的代理對象,auto_ptr對象間的賦值是一個需要特別注意的地方。簡單說來資源代理對象間賦值的語義不滿足“賦值相等”,其語義是資源管理權(quán)的轉(zhuǎn)移。

什么是“賦值相等”呢?比如:

int a;

int b = 10;

a = b; //這句話執(zhí)行后 a == b

但對于資源代理對象,這是不滿足的,比如:

auto_ptr a(null);

auto_ptr b(new int(123));

a = b; //這句話執(zhí)行后a != b,賦值的語義是b把資源的管理權(quán)交給了a

C#與C++資源管理方式對陣總結(jié)

對比介紹了C#和C++資源管理方式:GC和RAII。

本文來自Todd Wei博客園文章《C# vs C++之二:GC vs RAII

【編輯推薦】

  1. C++之運(yùn)算符重載,輸入輸出流詳細(xì)介紹
  2. C++、Java與C#的命名規(guī)范總結(jié)
  3. C++類成員函數(shù)的重載、覆蓋與隱藏
  4. Eclipse下C/C++環(huán)境搭建
  5. Java與C++語言在作用域上的差異淺析
責(zé)任編輯:彭凡 來源: 博客園
相關(guān)推薦

2024-03-04 10:53:08

RAIIC++開發(fā)

2009-08-19 09:57:01

C++ RAII

2010-01-28 14:54:01

C++資源管理

2010-02-05 13:52:04

C++資源管理

2010-01-28 15:09:36

C++資源管理

2025-02-18 00:08:00

代碼C++RAII

2021-06-09 09:49:35

C++RAII語言

2010-07-06 09:14:56

2011-06-09 15:04:22

RAII機(jī)制

2010-01-15 18:35:25

C++的類

2009-05-22 11:01:53

C++JavaC#

2009-08-13 17:30:30

C#構(gòu)造函數(shù)

2009-09-07 15:21:38

Java與C#事件處理

2009-08-19 10:09:21

C#和C++

2009-08-28 10:14:45

C#內(nèi)存泄露

2011-05-18 18:05:47

C#C++

2011-05-18 17:56:38

C#C++

2010-02-04 15:41:10

C++內(nèi)存管理

2010-03-09 19:39:37

python程序調(diào)試

2009-08-25 14:42:41

由C++轉(zhuǎn)向C#
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 中文字幕一区在线 | 粉嫩一区二区三区性色av | 久久久免费电影 | av黄色免费在线观看 | 色av一区二区三区 | 欧美性网| 国产高清在线精品 | 亚洲精品美女在线观看 | 亚洲精品欧美精品 | 国产在线视频一区 | 日本在线观看视频 | av天天操 | 老头搡老女人毛片视频在线看 | 国产日韩欧美 | 日韩欧美手机在线 | 中文字幕av一区二区三区 | 天天射色综合 | 夜夜爽99久久国产综合精品女不卡 | 91看片免费版 | 精品欧美一区二区三区久久久 | 亚洲视频不卡 | 在线观看黄色 | 天天躁日日躁狠狠躁2018小说 | 亚洲综合三区 | 欧美日韩在线一区 | 亚洲成人综合社区 | 久久国产亚洲 | 欧美一级在线免费 | 欧美一级毛片久久99精品蜜桃 | 国产精品自拍av | 日韩欧美在线观看 | 欧美一区二区三 | 一区二区三区小视频 | 国产精品一区二区福利视频 | 亚洲精品成人免费 | 国产精品一区二区三区在线播放 | 天堂三级 | 国产偷录视频叫床高潮对白 | 日韩欧美国产一区二区 | 亚洲高清在线免费观看 | 成人激情视频在线播放 |