重慶分公司,新征程啟航
為企業(yè)提供網(wǎng)站建設、域名注冊、服務器等服務
為企業(yè)提供網(wǎng)站建設、域名注冊、服務器等服務
1.B 2.B 3.C 4.A 5.C 6.D 7.B 8.B 9.A 10.C
創(chuàng)新互聯(lián)主營柘榮網(wǎng)站建設的網(wǎng)絡公司,主營網(wǎng)站建設方案,重慶APP軟件開發(fā),柘榮h5小程序開發(fā)搭建,柘榮網(wǎng)站營銷推廣歡迎柘榮等地區(qū)企業(yè)咨詢
1、編寫程序。從鍵盤輸入100個數(shù),將正數(shù)升序排列到數(shù)組的前端,把0放在中間,負數(shù)按降序排列在0的后面。
#include"stdio.h"
void main()
{
int i,j,k,s,a[100],b[100]={0},m=0,n=0;
printf("input:");
for(i=0;i100;i++)
scanf("%d",a[i]);
for(i=0,j=0;i100;i++)
if(a[i]0){b[j++]=a[i];m++;}//m正數(shù)個數(shù)
for(i=0,j=99;i100;i++)
if(a[i]0){b[j--]=a[i]; n++;}//n負數(shù)個數(shù)
for(i=0;im-1;i++)//正數(shù)排序
{ k=i
for(j=i+1;jm;j++)
if(b[i]b[j])k=j;
if(i!=k)
{s=b[i];b[i]=b[k];b[k]=s;}
}
for(i=100-n;i99;i++)//負數(shù)排序
{ k=i
for(j=i+1;j100;j--)
if(b[i]b[j])k=j;
if(i!=k)
{s=b[i];b[i]=b[k];b[k]=s;}
}
for(i=0;i100;i++)
printf("%d ",b[i]);
printf("\n")
}
類是編程人員表達自定義數(shù)據(jù)類型的C++機制。它和C語言中的結(jié)構(gòu)類似,C++類
支持數(shù)據(jù)抽象和面向?qū)ο蟮某绦蛟O計,從某種意義上說,也就是數(shù)據(jù)類型的設
計和實現(xiàn)。
一、類的設計
1.類的聲明
class 類名
{
private: //私有
...
public: //公有
...
};
2.類的成員
一般在C++類中,所有定義的變量和函數(shù)都是類的成員。如果是變量,我們就叫
它數(shù)據(jù)成員如果是函數(shù),我們就叫它成員函數(shù)。
3.類成員的可見性
private和public訪問控制符決定了成員的可見性。由一個訪問控制符設定的可
訪問狀態(tài)將一直持續(xù)到下一個訪問控制符出現(xiàn),或者類聲明的結(jié)束。私有成員
僅能被同一個類中的成員函數(shù)訪問,公有成員既可以被同一類中的成員函數(shù)訪
問,也可以被其他已經(jīng)實例化的類中函數(shù)訪問。當然,這也有例外的情況,這
是以后要討論的友元函數(shù)。
類中默認的數(shù)據(jù)類型是private,結(jié)構(gòu)中的默認類型是public。一般情況下,變
量都作為私有成員出現(xiàn),函數(shù)都作為公有成員出現(xiàn)。
類中還有一種訪問控制符protected,叫保護成員,以后再說明。
4.初始化
在聲明一個類的對象時,可以用圓括號()包含一個初始化表。
看下面一個例子:
#include iostream.h
class Box
{
private:
int height,width,depth; //3個私有數(shù)據(jù)成員
public:
Box(int,int,int);
~Box();
int volume(); //成員函數(shù)
};
Box::Box(int ht,int wd,int dp)
{
height=ht;
width=wd;
depth=dp;
}
Box::~Box()
{
//nothing
}
int Box::volume()
{
return height*width*depth;
}
int main()
{
Box thisbox(3,4,5); //聲明一個類對象并初始化
cout return 0;
}
當一個類中沒有private成員和protected成員時,也沒有虛函數(shù),并且不是從
其他類中派生出來的,可以用{}來初始化。(以后再講解)
5.內(nèi)聯(lián)函數(shù)
內(nèi)聯(lián)函數(shù)和普通函數(shù)的區(qū)別是:內(nèi)聯(lián)函數(shù)是在編譯過程中展開的。通常內(nèi)聯(lián)函
數(shù)必須簡短。定義類的內(nèi)聯(lián)函數(shù)有兩種方法:一種和C語言一樣,在定義函數(shù)時
使用關鍵字inline。如:
inline int Box::volume()
{
return height*width*depth;
}
還有一種方法就是直接在類聲明的內(nèi)部定義函數(shù)體,而不是僅僅給出一個函數(shù)
原型。我們把上面的函數(shù)簡化一下:
#include iostream.h
class Box
{
private:
int height,width,depth;
public:
Box(int ht,int wd,int dp)
{
height=ht;
width=wd;
depth=dp;
}
~Box();
int volume()
{
return height*width*depth;
}
};
int main()
{
Box thisbox(3,4,5); //聲明一個類對象并初始化
cout return 0;
}
這樣,兩個函數(shù)都默認為內(nèi)聯(lián)函數(shù)了。
嵌入式Linux操作系統(tǒng)學習規(guī)劃\x0d\x0aARM+LINUX路線,主攻嵌入式Linux操作系統(tǒng)及其上應用軟件開發(fā)目標: \x0d\x0a(1) 掌握主流嵌入式微處理器的結(jié)構(gòu)與原理(初步定為arm9) \x0d\x0a(2) 必須掌握一個嵌入式操作系統(tǒng) (初步定為uclinux或linux,版本待定) \x0d\x0a(3) 必須熟悉嵌入式軟件開發(fā)流程并至少做一個嵌入式軟件項目。 \x0d\x0a從事嵌入式軟件開發(fā)的好處是: \x0d\x0a(1)目前國內(nèi)外這方面的人都很稀缺。這一領域入門門檻較高,所以非專業(yè)IT人員很難切入這一領域;另一方面,是因為這一領域較新,目前發(fā)展太快,大多數(shù)人無條件接觸。 \x0d\x0a(2)與企業(yè)計算等應用軟件不同,嵌入式領域人才的工作強度通常低一些(但收入不低)。 \x0d\x0a(3)哪天若想創(chuàng)業(yè),搞自已的產(chǎn)品,嵌入式不像應用軟件那樣容易被盜版。硬件設計一般都是請其它公司給訂做(這叫“貼牌”:OEM),都是通用的硬件,我們只管設計軟件就變成自己的產(chǎn)品了。 \x0d\x0a(4)興趣所在,這是最主要的。 \x0d\x0a從事嵌入式軟件開發(fā)的缺點是: \x0d\x0a(1)入門起點較高,所用到的技術往往都有一定難度,若軟硬件基礎不好,特別是操作系統(tǒng)級軟件功底不深,則可能不適于此行。 \x0d\x0a(2)這方面的企業(yè)數(shù)量要遠少于企業(yè)計算類企業(yè)。 \x0d\x0a(3)有少數(shù)公司經(jīng)常要碩士以上的人搞嵌入式,主要是基于嵌入式的難度。但大多數(shù)公司也并無此要求,只要有經(jīng)驗即可。 \x0d\x0a(4)平臺依托強,換平臺比較辛苦。 \x0d\x0a興趣的由來: \x0d\x0a1、成功觀念不同,不虛度此生,就是我的成功。 \x0d\x0a2、喜歡思考,挑戰(zhàn)邏輯思維。 \x0d\x0a3、喜歡C \x0d\x0aC是一種能發(fā)揮思維極限的語言。關于C的精神的一些方面可以被概述成短句如下: \x0d\x0a相信程序員。 \x0d\x0a不要阻止程序員做那些需要去做的。 \x0d\x0a保持語言短小精干。 \x0d\x0a一種方法做一個操作。 \x0d\x0a使得它運行的夠快,盡管它并不能保證將是可移植的。 \x0d\x0a4、喜歡底層開發(fā),討厭vb類開發(fā)工具(并不是說vb不好)。 \x0d\x0a5、發(fā)展前景好,適合創(chuàng)業(yè),不想自己要死了的時候還是一個工程師。 \x0d\x0a方法步驟: \x0d\x0a1、基礎知識: \x0d\x0a目的:能看懂硬件工作原理,但重點在嵌入式軟件,特別是操作系統(tǒng)級軟件,那將是我的優(yōu)勢。 \x0d\x0a科目:數(shù)字電路、計算機組成原理、嵌入式微處理器結(jié)構(gòu)。 \x0d\x0a匯編語言、C/C++、編譯原理、離散數(shù)學。 \x0d\x0a數(shù)據(jù)結(jié)構(gòu)和算法、操作系統(tǒng)、軟件工程、網(wǎng)絡、數(shù)據(jù)庫。 \x0d\x0a方法:雖科目眾多,但都是較簡單的基礎,且大部分已掌握。不一定全學,可根據(jù)需要選修。 \x0d\x0a主攻書籍:the c++ programming language(一直沒時間讀)、數(shù)據(jù)結(jié)構(gòu)-C2。 \x0d\x0a\x0d\x0a2、學習linux: \x0d\x0a目的:深入掌握linux系統(tǒng)。 \x0d\x0a 方法:使用linux—〉linxu系統(tǒng)編程開發(fā)—〉驅(qū)動開發(fā)和分析linux內(nèi)核。先看深,那主講原理??磶妆楹螅辞榫胺治?,對照深看,兩本交叉,深是綱,情是目。剖析則是0.11版,適合學習。最后深入代碼。 \x0d\x0a主攻書籍:linux內(nèi)核完全剖析、unix環(huán)境高級編程、深入理解linux內(nèi)核、情景分析和源代。 \x0d\x0a3、學習嵌入式linux: \x0d\x0a目的:掌握嵌入式處理器其及系統(tǒng)。 \x0d\x0a方法:(1)嵌入式微處理器結(jié)構(gòu)與應用:直接arm原理及匯編即可,不要重復x86。 \x0d\x0a (2)嵌入式操作系統(tǒng)類:ucOS/II簡單,開源,可供入門。而后深入研究uClinux。 \x0d\x0a (3)必須有塊開發(fā)板(arm9以上),有條件可參加培訓(進步快,能認識些朋友)。 \x0d\x0a 主攻書籍:毛德操的《嵌入式系統(tǒng)》及其他arm9手冊與arm匯編指令等。 \x0d\x0a\x0d\x0a4、深入學習: \x0d\x0a A、數(shù)字圖像壓縮技術:主要是應掌握MPEG、mp3等編解碼算法和技術。 \x0d\x0a B、通信協(xié)議及編程技術:TCP/IP協(xié)議、802.11,Bluetooth,GPRS、GSM、CDMA等。 \x0d\x0a\x0d\x0a2010-8-21 16:46 回復 \x0d\x0a122.90.173.* 2樓\x0d\x0a\x0d\x0a C、網(wǎng)絡與信息安全技術:如加密技術,數(shù)字證書CA等。 \x0d\x0a D、DSP技術:Digital Signal Process,DSP處理器通過硬件實現(xiàn)數(shù)字信號處理算法。 \x0d\x0a 說明:太多細節(jié)未說明,可根據(jù)實際情況調(diào)整。重點在于1、3,不必完全按照順序作。對于學習c++,理由是c++不只是一種語言,一種工具,她還是一種藝術,一種文化,一種哲學理念、但不是拿來炫耀得東西。對于linux內(nèi)核,學習編程,讀一些優(yōu)秀代碼也是有必要的。 \x0d\x0a 注意: 要學會舉一反多,有強大的基礎,很多東西簡單看看就能會。想成為合格的程序員,前提是必須熟練至少一種編程語言,并具有良好的邏輯思維。一定要理論結(jié)合實踐。 \x0d\x0a 不要一味鉆研技術,雖然擠出時間是很難做到的,但還是要留點余地去完善其他的愛好,比如宇宙,素描、機械、管理,心理學、游戲、科幻電影。還有一些不愿意做但必須要做的! \x0d\x0a 技術是通過編程編程在編程編出來的。永遠不要夢想一步登天,不要做浮躁的人,不要覺得路途漫上。而是要編程編程在編程,完了在編程,在編程!等機會來了在創(chuàng)業(yè)(不要相信有奇跡發(fā)生,盲目創(chuàng)業(yè)很難成功,即便成功了發(fā)展空間也不一定很大)。 \x0d\x0a\x0d\x0a 嵌入式書籍推薦 \x0d\x0a Linux基礎 \x0d\x0a 1、《Linux與Unix Shell 編程指南》 \x0d\x0a C語言基礎 \x0d\x0a 1、《C Primer Plus,5th Edition》【美】Stephen Prata著 \x0d\x0a 2、《The C Programming Language, 2nd Edition》【美】Brian W. Kernighan David M. Rithie(K R)著 \x0d\x0a 3、《Advanced Programming in the UNIX Environment,2nd Edition》(APUE) \x0d\x0a 4、《嵌入式Linux應用程序開發(fā)詳解》 \x0d\x0a Linux內(nèi)核 \x0d\x0a 1、《深入理解Linux內(nèi)核》(第三版) \x0d\x0a 2、《Linux內(nèi)核源代碼情景分析》毛德操 胡希明著 \x0d\x0a 研發(fā)方向 \x0d\x0a 1、《UNIX Network Programming》(UNP) \x0d\x0a 2、《TCP/IP詳解》 \x0d\x0a 3、《Linux內(nèi)核編程》 \x0d\x0a 4、《Linux設備驅(qū)動開發(fā)》(LDD) \x0d\x0a 5、《Linux高級程序設計》 楊宗德著\x0d\x0a 硬件基礎 \x0d\x0a 1、《ARM體系結(jié)構(gòu)與編程》杜春雷著 \x0d\x0a 2、S3C2410 Datasheet \x0d\x0a 英語基礎 \x0d\x0a 1、《計算機與通信專業(yè)英語》 \x0d\x0a 系統(tǒng)教程 \x0d\x0a 1、《嵌入式系統(tǒng)——體系結(jié)構(gòu)、編程與設計》 \x0d\x0a 2、《嵌入式系統(tǒng)——采用公開源代碼和StrongARM/Xscale處理器》毛德操 胡希明著 \x0d\x0a 3、《Building Embedded Linux Systems》 \x0d\x0a 4、《嵌入式ARM系統(tǒng)原理與實例開發(fā)》 楊宗德著\x0d\x0a 理論基礎 \x0d\x0a 1、《算法導論》 \x0d\x0a 2、《數(shù)據(jù)結(jié)構(gòu)(C語言版)》 \x0d\x0a 3、《計算機組織與體系結(jié)構(gòu)?性能分析》 \x0d\x0a 4、《深入理解計算機系統(tǒng)》【美】Randal E. Bryant David O''Hallaron著 \x0d\x0a 5、《操作系統(tǒng):精髓與設計原理》 \x0d\x0a 6、《編譯原理》 \x0d\x0a 7、《數(shù)據(jù)通信與計算機網(wǎng)絡》 \x0d\x0a 8、《數(shù)據(jù)壓縮原理與應用》 \x0d\x0a\x0d\x0a C語言書籍推薦 \x0d\x0a 1. The C programming language 《C程序設計語言》 \x0d\x0a 2. Pointers on C 《C和指針》 \x0d\x0a 3. C traps and pitfalls 《C陷阱與缺陷》 \x0d\x0a 4. Expert C Lanuage 《專家C編程》 \x0d\x0a 5. Writing Clean Code -----Microsoft Techiniques for Developing Bug-free C Programs \x0d\x0a 《編程精粹--Microsoft 編寫優(yōu)質(zhì)無錯C程序秘訣》 \x0d\x0a 6. Programming Embedded Systems in C and C++ 《嵌入式系統(tǒng)編程》 \x0d\x0a 7.《C語言嵌入式系統(tǒng)編程修煉》 \x0d\x0a 8.《高質(zhì)量C++/C編程指南》林銳 \x0d\x0a 盡可能多的編碼,要學好C,不能只注重C本身。算法,架構(gòu)方式等都很重要。 \x0d\x0a\x0d\x0a這里很多書其實是推薦而已,不必太在意,關鍵還是基礎,才是重中之重!??!
摘 要:構(gòu)造函數(shù)與析構(gòu)函數(shù)是一個類中看似較為簡單的兩類函數(shù),但在實際運用過程中總會出現(xiàn)一些意想不到的運行錯誤。本文將較系統(tǒng)的介紹構(gòu)造函數(shù)與析構(gòu)函數(shù)的原理及在C#中的運用,以及在使用過程中需要注意的若干事項。
關鍵字:構(gòu)造函數(shù);析構(gòu)函數(shù);垃圾回收器;非托管資源;托管資源
一.構(gòu)造函數(shù)與析構(gòu)函數(shù)的原理
作為比C更先進的語言,C#提供了更好的機制來增強程序的安全性。C#編譯器具有嚴格的類型安全檢查功能,它幾乎能找出程序中所有的語法問題,這的確幫了程序員的大忙。但是程序通過了編譯檢查并不表示錯誤已經(jīng)不存在了,在“錯誤”的大家庭里,“語法錯誤”的地位只能算是冰山一角。級別高的錯誤通常隱藏得很深,不容易發(fā)現(xiàn)。
根據(jù)經(jīng)驗,不少難以察覺的程序錯誤是由于變量沒有被正確初始化或清除造成的,而初始化和清除工作很容易被人遺忘。微軟利用面向?qū)ο蟮母拍钤谠O計C#語言時充分考慮了這個問題并很好地予以解決:把對象的初始化工作放在構(gòu)造函數(shù)中,把清除工作放在析構(gòu)函數(shù)中。當對象被創(chuàng)建時,構(gòu)造函數(shù)被自動執(zhí)行。當對象消亡時,析構(gòu)函數(shù)被自動執(zhí)行。這樣就不用擔心忘記對象的初始化和清除工作。
二.構(gòu)造函數(shù)在C#中的運用
構(gòu)造函數(shù)的名字不能隨便起,必須讓編譯器認得出才可以被自動執(zhí)行。它的命名方法既簡單又合理:讓構(gòu)造函數(shù)與類同名。除了名字外,構(gòu)造函數(shù)的另一個特別之處是沒有返回值類型,這與返回值類型為void的函數(shù)不同。如果它有返回值類型,那么編譯器將不知所措。在你可以訪問一個類的方法、屬性或任何其它東西之前, 第一條執(zhí)行的語句是包含有相應類的構(gòu)造函數(shù)。甚至你自己不寫一個構(gòu)造函數(shù),也會有一個缺省構(gòu)造函數(shù)提供給你。
class TestClass
{
public TestClass(): base() {} // 由CLR提供
}
下面列舉了幾種類型的構(gòu)造函數(shù)
1)缺省構(gòu)造函數(shù)
class TestClass
{
public TestClass(): base() {}
}
上面已介紹,它由系統(tǒng)(CLR)提供。
2)實例構(gòu)造函數(shù)
實例構(gòu)造函數(shù)是實現(xiàn)對類中實例進行初始化的方法成員。如:
using System;
class Point
{
public double x, y;
public Point()
{
this.x = 0;
this.y = 0;
}
public Point(double x, double y)
{
this.x = x;
this.y = y;
}
}
class Test
{
static void Main()
{
Point a = new Point();
Point b = new Point(3, 4); // 用構(gòu)造函數(shù)初始化對象
}
}
聲明了一個類Point,它提供了兩個構(gòu)造函數(shù)。它們是重載的。一個是沒有參數(shù)的Point構(gòu)造函數(shù)和一個是有兩個double參數(shù)的Point構(gòu)造函數(shù)。如果類中沒有提供這些構(gòu)造函數(shù),那么會CLR會自動提供一個缺省構(gòu)造函數(shù)的。但一旦類中提供了自定義的構(gòu)造函數(shù),如Point()和Point(double x, double y),則缺省構(gòu)造函數(shù)將不會被提供,這一點要注意。
3) 靜態(tài)構(gòu)造函數(shù)
靜態(tài)構(gòu)造函數(shù)是實現(xiàn)對一個類進行初始化的方法成員。它一般用于對靜態(tài)數(shù)據(jù)的初始化。靜態(tài)構(gòu)造函數(shù)不能有參數(shù),不能有修飾符而且不能被調(diào)用,當類被加載時,類的靜態(tài)構(gòu)造函數(shù)自動被調(diào)用。如:
using System.Data;
class Employee
{
private static DataSet ds;
static Employee()
{
ds = new DataSet(...);
}
}
聲明了一個有靜態(tài)構(gòu)造函數(shù)的類Employee。注意靜態(tài)構(gòu)造函數(shù)只能對靜態(tài)數(shù)據(jù)成員進行初始化,而不能對非靜態(tài)數(shù)據(jù)成員進行初始化。但是,非靜態(tài)構(gòu)造函數(shù)既可以對靜態(tài)數(shù)據(jù)成員賦值,也可以對非靜態(tài)數(shù)據(jù)成員進行初始化。
如果類僅包含靜態(tài)成員,你可以創(chuàng)建一個private的構(gòu)造函數(shù):private TestClass() {…},但是private意味著從類的外面不可能訪問該構(gòu)造函數(shù)。所以,它不能被調(diào)用,且沒有對象可以被該類定義實例化。
以上是幾種類型構(gòu)造函數(shù)的簡單運用,下面將重點介紹一下在類的層次結(jié)構(gòu)中(即繼承結(jié)構(gòu)中)基類和派生類的構(gòu)造函數(shù)的使用方式。派生類對象的初始化由基類和派生類共同完成:基類的成員由基類的構(gòu)造函數(shù)初始化,派生類的成員由派生類的構(gòu)造函數(shù)初始化。
當創(chuàng)建派生類的對象時,系統(tǒng)將會調(diào)用基類的構(gòu)造函數(shù)和派生類的構(gòu)造函數(shù),構(gòu) 造函數(shù)的執(zhí)行次序是:先執(zhí)行基類的構(gòu)造函數(shù),再執(zhí)行派生類的構(gòu)造函數(shù)。如果派生類又有對象成員,則,先執(zhí)行基類的構(gòu)造函數(shù),再執(zhí)行成員對象類的構(gòu)造函數(shù),最后執(zhí)行派生類的構(gòu)造函數(shù)。
至于執(zhí)行基類的什么構(gòu)造函數(shù),缺省情況下是執(zhí)行基類的無參構(gòu)造函數(shù),如果要執(zhí)行基類的有參構(gòu)造函數(shù),則必須在派生類構(gòu)造函數(shù)的成員初始化表中指出。如:
class A
{ private int x;
public A( ) { x = 0; }
public A( int i ) { x = i; }
};
class B : A
{ private int y;
public B( ) { y = 0; }
public B( int i ) { y = i; }
public B( int i, int j ):A(i) { y = j; }
};
B b1 = new B(); //執(zhí)行基類A的構(gòu)造函數(shù)A(),再執(zhí)行派生類的構(gòu)造函數(shù)B()
B b2 = new B(1); //執(zhí)行基類A的構(gòu)造函數(shù)A(),再執(zhí)行派生類的構(gòu)造函數(shù)B(int)
B b3 = new B(0,1); //執(zhí)行執(zhí)行基類A的構(gòu)造函數(shù)A(int) ,再執(zhí)行派生類的
構(gòu)造函數(shù)B(int,int)
在這里構(gòu)造函數(shù)的執(zhí)行次序是一定要分析清楚的。另外,如果基類A中沒有提供無參構(gòu)造函數(shù)public A( ) { x = 0; },則在派生類的所有構(gòu)造函數(shù)成員初始化表中必須指出基類A的有參構(gòu)造函數(shù)A(i),如下所示:
class A
{ private int x;
public A( int i ) { x = i; }
};
class B : A
{ private int y;
public B():A(i) { y = 0; }
public B(int i):A(i) { y = i; }
public B(int i, int j):A(i) { y = j; }
};
三.析構(gòu)函數(shù)和垃圾回收器在C#中的運用
析構(gòu)函數(shù)是實現(xiàn)銷毀一個類的實例的方法成員。析構(gòu)函數(shù)不能有參數(shù),不能任何修飾符而且不能被調(diào)用。由于析構(gòu)函數(shù)的目的與構(gòu)造函數(shù)的相反,就加前綴‘~’以示區(qū)別。
雖然C#(更確切的說是CLR)提供了一種新的內(nèi)存管理機制---自動內(nèi)存管理機制(Automatic memory management),資源的釋放是可以通過“垃圾回收器” 自動完成的,一般不需要用戶干預,但在有些特殊情況下還是需要用到析構(gòu)函數(shù)的,如在C#中非托管資源的釋放。
資源的.釋放一般是通過"垃圾回收器"自動完成的,但具體來說,仍有些需要注意的地方:
1. 值類型和引用類型的引用其實是不需要什么"垃圾回收器"來釋放內(nèi)存的,因為當它們出了作用域后會自動釋放所占內(nèi)存,因為它們都保存在棧(Stack)中;
2. 只有引用類型的引用所指向的對象實例才保存在堆(Heap)中,而堆因為是一個自由存儲空間,所以它并沒有像"棧"那樣有生存期("棧"的元素彈出后就代表生存期結(jié)束,也就代表釋放了內(nèi)存),并且要注意的是,"垃圾回收器"只對這塊區(qū)域起作用;
然而,有些情況下,當需要釋放非托管資源時,就必須通過寫代碼的方式來解決。通常是使用析構(gòu)函數(shù)釋放非托管資源,將用戶自己編寫的釋放非托管資源的代碼段放在析構(gòu)函數(shù)中即可。需要注意的是,如果一個類中沒有使用到非托管資源,那么一定不要定義析構(gòu)函數(shù),這是因為對象執(zhí)行了析構(gòu)函數(shù),那么"垃圾回收器"在釋放托管資源之前要先調(diào)用析構(gòu)函數(shù),然后第二次才真正釋放托管資源,這樣一來,兩次刪除動作的花銷比一次大多的。下面使用一段代碼來示析構(gòu)函數(shù)是如何使用的:
public class ResourceHolder
{
~ResourceHolder()
{
// 這里是清理非托管資源的用戶代碼段
}
}
四.小結(jié)
構(gòu)造函數(shù)與析構(gòu)函數(shù)雖然是一個類中形式上較簡單的函數(shù),但它們的使用決非看上去那么簡單,因此靈活而正確的使用構(gòu)造函數(shù)與析構(gòu)函數(shù)能夠幫你更好的理解CLR的內(nèi)存管理機制,以及更好的管理系統(tǒng)中的資源。
1、首先C語言沒辦法實現(xiàn)構(gòu)造函數(shù)和析構(gòu)函數(shù),因為C語言是面向過程的語言,沒有定義面向?qū)ο蟮腸lass概念。C++語言是以C語言為基礎擴展出來的一種編程語言,它在繼承了C語言的基礎上,增加了面向?qū)ο蟮木幊谭椒?,其中就包含了class。
2、如果你所描述的c語言是指C++語言,那么是可以自已定義并實現(xiàn)CString類的一些功能。因為CString類是微軟VC++ MFC實現(xiàn)的基礎類,而非C++標準類庫,所以CString類定義中使用了一些AFX函數(shù),依賴于MFC環(huán)境,所以想自定義一個完全取代CString的類很困難,也無意義。
3、如果只是需要學習CString的構(gòu)造函數(shù)、析構(gòu)函數(shù)及賦值函數(shù),可以參考MFC類庫源文件:
\MICROSOFT VISUAL STUDIO\VC98\MFC\Include\AFX.INL
\MICROSOFT VISUAL STUDIO\VC98\MFC\SRC\STRCORE.CPP
\MICROSOFT VISUAL STUDIO\VC98\MFC\SRC\WINSTR.CPP
任何時候都可以,只要你做好了準備迎接它。C語言會帶你進入一個真正的程序世界。
為什么要學習、使用C語言?
C語言相比C++的優(yōu)點之一就是最小驚訝原則,一是一二是二,不會在私底下產(chǎn)生一些莫名其妙的額外產(chǎn)物。用C++做個例子,比如這樣一個函數(shù)原型void PassWithClassValue(COneClass clsParam1),稍微了解C++的朋友都會知道,如果你沒有實現(xiàn)COneClass的拷貝構(gòu)造函數(shù),編譯器會好心的幫你實現(xiàn)一個,而且在調(diào)用這個函數(shù)PassWithClassValue的時候,偷偷地調(diào)用拷貝構(gòu)造函數(shù)產(chǎn)生一個臨時對象作為參數(shù)傳遞,對于某些情況,比如編寫操作系統(tǒng)這類必須優(yōu)化性能的情景下,這些自以為是的東西是非常邪惡的事情。
C語言本身只提供必要的語言特性,其它復雜一點功能如文件處理、數(shù)學計算等等都以庫函數(shù)方式提供,甚至連malloc、free這種“必須有”的功能,也是以標準庫函數(shù)的方式提供,而不是作為C語言核心出現(xiàn)。在偉大的著名的無所不包的《KR》開頭部分就提到了,for其實可以通過while來完成,只不過for可以寫的更簡潔,言外之意,對于C語言for其實不是必要的。跑題一點說,在其它程序語言中Lua可以說繼承了C語言簡潔的設計哲學,甚至連continue這種幾乎必備的關鍵字都一直拒絕加入,在Lua的maillist以及wiki里都提到過continue這個問題,Lua語言維護者認為continue對于Lua而言不是必要的,也不考慮在后續(xù)版本中添加這個關鍵字。這種簡潔哲學也讓C語言的可移植性、便攜性特別優(yōu)秀,也使得很多嵌入式系統(tǒng)依然使用C語言作為主要編程工作語言。
Java語言有一個口號:“一次編寫,處處運行”,就是跨平臺這個噱頭。實際上C語言從早期開始就幾乎達到了“一次編寫,處處編譯”,在ANSI在1989年統(tǒng)一了C語言標準以后(稱之為C89),只要特定平臺上的編譯器完整實現(xiàn)了C89標準,而且你的代碼沒有使用某些特殊的擴展(GCC以及微軟都有自己的編譯器特定擴展),那么代碼一定可以編譯通過,再實現(xiàn)一下操作系統(tǒng)相關的函數(shù)庫,C語言的移植就是很簡單的事情??梢杂肔ua作為例子,Lua本身是完全遵循C89標準,沒有使用任何特定擴展,這也保證了有C語言編譯器的平臺,都可以編譯使用Lua??梢跃幾g運行C語言的硬件平臺可以從A排到Z,真是非常有意思的事情。
C語言也是一個比較少見的應用領域極為廣泛的語言。比如編寫操作系統(tǒng)這種高難問題,只有C++、匯編語言可以做到。C語言可以編寫服務器端軟件如Apache、Nginx,或者編寫GUI程序,如GTK。大多數(shù)程序語言的第一版是通過C語言實現(xiàn),借助前面提到的“一次編寫處處編譯”,最大的保證了這些程序語言的可移植性。在Web開發(fā)領域,C語言的應用相對較少,這也是一種取舍的結(jié)果,Web開發(fā)需要使用PHP、Ruby、Python這樣的動態(tài)語言,可以快速上線快速修改,可以最大程度滿足用戶時時變化的需求,這也是C語言的弱項。如果把程序語言的應用領域從硬件到管理軟件、Web程序做一個很粗略從下到上的排列,C語言適合領域是比較底層靠近硬件的部分,而新興語言比較偏重于高層管理或者Web開發(fā)這種相對貼近最終用戶的領域。比較流行的混合開發(fā)模式是使用C語言編寫底層高性能部分代碼或后臺服務器代碼,而使用動態(tài)語言如Python做前端開發(fā),充分發(fā)揮它們各自的優(yōu)勢力量。
提到C語言的缺點,常常是它缺少這種或者那種特性,比如有人建議加入GC,有人建議加入并行或者并發(fā)支持,有人提到?jīng)]有一個比較完整的類似C++的異常策略。這些特性有的可以通過引入第三方庫來實現(xiàn),但C語言的設計哲學其實決定了它不會像C++那樣“非常強大”。即使引入了某些人期望的特性,依然會是某些人喜歡某些人不喜歡的情形,現(xiàn)在的功能對于C語言應用領域來說已經(jīng)夠用,其它特性可以通過特定程序語言實現(xiàn),并且通過C API與C語言編寫的程序進行交互。任何一個工匠都不可能只使用一個工具完成他的工作,不同工具結(jié)合起來才能更快更好的完成任務。
提到C API,也稍微介紹一下,我們知道windows操作系統(tǒng)的api也好,Linux的系統(tǒng)api也好,或者是想給Ruby、Python編寫擴展模塊,C語言形式的函數(shù)定義都是唯一的選擇。C語言就好像是一個中間層或者是膠水,如果想把不同編程語言實現(xiàn)的功能模塊混合使用,C語言是最佳的選擇。
提了這么多關于C語言的好處,那么學習C語言是否適合就看你自己的判斷了,例如要進行一個嵌入式項目,或者需要進行服務器端開發(fā),或者寫一個性能相關的組件等等,C語言都是比較好用的選擇。另外也可以在C++的使用過程中有意的使用C語言的思考方式,汲取C語言簡潔明快清晰地設計思路,對編程設計水平會有很大的提高。