青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

[翻譯]嵌入式C++編程準則

   譯自:http://www.caravan.net/ec2plus/guide.html


 

 

 A     代碼從C語言到C++語言的移植

A1     字符常量

              注解

                     C中,字符常量是int類型,而在C++中,其類型為char.

 

              示例

                     I = sizeof(‘a’);

 

C中,i保存的實際內容是sizeof(int)的計算結果值,該值要比1大。而在C++中,i存儲的實際內容是sizeof(char),該值總是為1

             

              準則

當將C代碼移植為C++代碼時,所有對字符常量的sizeof有依賴關系的表達式都要被移除。


 

 

A2     文件范圍內的對象聲明

              注解

C++中,在文件范圍內,聲明一個沒有指定存儲類型標志符的對象時,實際上是定義該對象為外部鏈接符號(extern)。如果這個定義中沒有初始化表達式,那么該對象將被初始化為0。相比較于C來說,C++程序中聲明的對象會被明確的定義且只定義過1次。

而在C中,這將被視為一個暫時的定義,這種定義方式在一個translation unit中允許出現多次。

 

示例

          int a;          /* (1) */
          int a = 10;     /* (2) */

C中,(1)是一種暫時性的定義。由于(2)被看作是確切的定義,(1)被看作是只是聲明一個變量。

C++中,(1)、(2)都被認為是定義式。由于存在(1)、(2)兩個重復定義式,因此是一個錯誤。

 

              準則

C++中,如果想在文件范圍內僅聲明一個對象(而不是定義該對象),那么該對象不能擁有初始化表達式,并且需要使用extern來修飾。

聲明于文件范圍內的每一個對象只能顯式的被定義一次。除了一次聲明外,其余所有聲明都必須具有extern修飾并且沒有初始化表達式。


 

 

A.3   const 類型修飾符
      注解
     C中,在文件范圍內,一個使用const修飾而未指明存儲類型的對象具有外部鏈接屬性。而在C++中,它具有內部連接屬性。
 
示例
          +- file1 --------------------+
          |      extern const int n;   |
          +----------------------------+
          +- file2 --------------------+
          |      const int n = 10;     |
          +----------------------------+
C中,文件file2中的對象n具有外部連接屬性,因此,文件file1中對象n(該對象同樣具有外部鏈接屬性)可以引用它。在C++中,文件file2中的對象n具有的屬性是內部鏈接的,因此,file1中的對象n無法引用到它。
          
      準則
           使用extern顯示修飾const對象,使該對象具有外部鏈接屬性。


 

 

A.4    void*的轉型
      注解
          C語言標準允許void*轉換為T*T表示任何對象),而在C++中沒有這樣的標準。在C++中類似的轉換需要顯示轉換來完成。
  下面這些C標準庫函數都返回void*
              calloc, malloc, realloc, bsearch, memcpy, memmove,
              memchr, memset
   C++中,將這些函數的返回值賦值給一個非void*的指針時,需要
顯示轉換。
      示例
          int* p;
          p = malloc(10 * sizeof(int));
 
          C++中,對指針p的賦值需要顯示的轉換,如:
 
          p = (int *)malloc(10 * sizeof(int));
 
      準則
  C++中使用new來代替callocmallocrealloc(參考A.12);
忽略memcpy, memmove, 以及memset的返回值(通常這些返回值由函數的第一個參數轉換而來);對于其他所有返回void*函數(包括標準庫函數和用戶自定義函數),需要使用顯式的轉換來將返回值轉換為其他指針類型。


 

 

A.5   枚舉類型
      注解
           C中的枚舉變量是整型。程序中,枚舉類型和整型可以互相轉換,而不需要顯式的轉換。C程序允許枚舉類型對象進行++--運算。
           C++中的枚舉是一種用戶自定義類型。C++標準允許枚舉類型轉換為整型,但從整型轉換為枚舉類型是非法的。C++程序中還不能將內置的++以及符合運算符(如+=)作用于枚舉類型變量上。
      示例
          enum RGB { red, green, blue } rgb;
          ++rgb;
         
         如果表達式(++rgb)采用內置的++運算符,那么在C++中這是一個錯誤表達式。該表達式的語意相當于:
         rgb = rgb + 1;
          上面的表達式在C++中還是錯誤的。而像下面這樣,對枚舉值進行顯示的轉換就是正確的:
          rgb = RGB(rgb + 1);
          最好的解決方法是為枚舉類型RGB實現一個++運算符。
          RBG &operator++(RGB &x)
          {
              return x = RGB(x + 1);
          }
        
      準則
     C程序移植為C++程序時,在需要的時候,要為枚舉類型實現類型安全的++--操作符。
 


 

 

A.6    在轉型、參數聲明、sizeof中定義類型
       注解
          C中,轉型表達式、參數聲明以及sizeof表達式中都可以進行類
型聲明,而在C++中則不能。
 
示例
          void func(struct TAG { int a; } st)
          {
              ...
          }
         如上所示,TAG在參數聲明是被定義。
        準則
          把在參數中聲明的類型的定義式,挪到函數聲明式作用域開始處,或者大于該作用域的某處。
 
           在轉型和sizeof表達式作用域開始處,或者大于該作用域的某處定義類型。


 

 

A.7   忽略局部對象定義式的控制流程跳轉
        注解
         C中,gotoswitch語句可以使控制流程跳過塊作用域內的局
部對象聲明式,甚至有可能是對象的初始化式。而在C++中不存在這種跳轉。
 
示例
          goto LABEL;
          {
              int v = 0;
              ...
          LABEL:
              ...
          }
           C中,上面的代碼是合法的,它假設標簽LABEL之后的代碼不依賴于整型變量v的初值0。而在C++中,這段代碼總是不能通過編譯。
       準則
            確保gotoswitch語句沒有跳過局部對象的初始化式。


 

 

A.8   字符數組的初始化
       注解
          C中,允許使用字符串來初始化一個字符數組。初始化表達式中,數組可以比字符串少一個字符空間(‘\0’字符)。在C++中數組則必須能完全容納字符串。
      示例
          char s[3] = "abc";
           盡管常量字符串為4個字符大小,但數組s的大小為3。這種做法在C中合法,而在C++中非法。
      準則
          為了容納‘\0’,請確保字符數組大小要比字符串長度大1。因而,有必要將字符數組大小指定為字符串長度+1。(也即:char s[4] = "abc";
          然而,為了使定義式自適應于不同的常量字符串,在定義式中不指定數組大小不失為一種好方法(即:char s[] = "abc";)。


 

 

A.9   原型聲明
       注解
          C++程序要求在使用函數之前必須聲明該函數原型。此外,C++程序會將函數聲明式f()解釋為f(void)----不帶參數的函數。而在C中,這樣的行為是不確定的。
      示例
          extern void func();
          ....
          sub();
          func(0);
          因為沒有sub函數的聲明,因此調用該函數是錯誤的。由于聲明式中函數不帶參數,因此以0為參數調用func也是個錯誤。
      準則
          確保被調用的函數已經被聲明。為了強調函數f不帶參數,好的做法是在聲明函數時,將參數聲明為void,即聲明式為:f(void).


 

 

A.10 C++增加的關鍵字
     注解
          C中沒有下面的C++關鍵字:
          asm             bool            catch           class
          const_cast      delete          dynamic_cast    explicit
          false           friend          inline          mutable
          namespace       new             operator        private
          protected       public          reinterpret_cast
          static_cast     template        this            throw
          true            try             typeid          typename
          using           virtual         wchar_t

示例

          int class, new, old;

         準則

                   確保沒有使用C++關鍵字作為標記符。


 

 

A.11 嵌套類型的作用域
     注解
          C結構體或聯合體內定義嵌套類型,該類型的作用域終止點和該結構
體或聯合體相同。而C++中定義的嵌套類型作用域終結于該結構或聯合體。
示例
          struct S {
              int a;
              struct T {
                  int t;
              } b;
              int c;
              enum E { V1, V2 } e;
          };
 
          struct T x;
          enum E y;
         xy的聲明在C程序中是合法的,但在C++中非法。在C++程序中,
在類S中定義的類型TE的作用域不會超過類S的定義范圍。
準則
    除非只是在結構體或聯合體內使用定義的嵌套類型,否則不在嵌套作用域內定義類型。


 

 

A.12 動態內存管理
     注解
          newdeletemallocfree沒有采用相同的內存管理策略。因此,
除非已經使用new獲取了內存,否則應用程序中不能使用delete來釋放內
存。同樣,除非使用了malloc分配內存,否則不能使用free來釋放內存。
 示例
          int (*p)[10];
          p = (int (*)[10])malloc(sizeof(*p));
          ....
          delete p;
 
          這里的delete具有未定義的行為。
     準則
        C++中避免使用malloccallocreallocfree函數,而僅使用
new/delete.


 

 

A.13 '/'之后的'/*'
     注解
        C++程序具有‘//’的注釋風格,因此緊接在符號‘/’之后的C風格
注釋‘/**/’,會被C++程序作為理解為‘//’后接‘**/’
示例
          i = j //* comment */ k ;
         //’被解釋為注釋分隔符,因而表達式被解釋為‘i=j’而不是‘i=j/k’。
準則
    盡量避免緊接著符號‘/’后寫C風格注釋‘/**/’.

 


 

 

B.    關于代碼容量的準則
B.1   對象初始化
       注解
有很多方法來初始化某個對象,有些初始化方法將會產生不必要的
臨時對象,從而導致代碼量膨脹。
     例如:
          T x(i)        // (1)
 
          T x = i;      // (2)
 
          T x = T(i)    // (3)
 
          T x;          // (4)
          x = i;        //
(1) 直接使用構造函數來初始化對象x,這樣就不會產生臨時對象。
調用形式類似于:
x.T(i);             // x對象調用構造函數
(2) 在某些實現中,方法(2)類似于方法(1),即對象x直接調用
構造函數。而在另外一些實現中,該方法會先使用構造函數生成一個臨時對象,然后將該臨時對象作為對象x的初始值。調用形式類似于:
              temp.T(i);        // 生成temp
              x.T(temp);        // x調用拷貝構造函數
              temp.~T();        // 析構temp
(3) 等同于(2
(4) 使用T的默認構造函數來初始化x,然后調用賦值操作符將新值
賦給x。賦值操作符可能會釋放x正在使用的資源,并重新為x獲取新的資源。
              x.T();           // x調用默認構造函數
              x.operator=(i); // x調用賦值操作符
       準則
            在上面的四種方法中,優先考慮方法(1)。
 


 

 

B.2   inline標記符
     注解
          內聯減少了函數進出棧上的管理開銷,但這也同時增加了代碼容量。
          在內內部定義的成員函數默認是內聯的。
     準則
          僅對小函數進行inline修飾。在類體之外定義所有不適合作為內聯函數的成員方法,從而使得該成員不是內聯函數。


 

 

B.3   返回值中的臨時對象
     注解
         函數按值返回一個對象時,可能需要創建并銷毀一個臨時對象,從而
導致代碼量增加并且帶來運行時開銷。
 示例
          class Matrix {
              int a, b;
          public:
              Matrix &operator+=(const Matrix &);
              friend
                  Matrix operator+(const Matrix &, const Matrix &);
          };
 
          Matrix operator +(const Matrix &, const Matrix &)
          {
              ...
          }
 
          void func()
          {
              Matrix a,b;
              a = a + b;        // (1)
              a += b;           // (2)
          }
          函數func在(1)處調用了+操作符,該操作符按值返回一個Matrix
對象。在某些編譯器實現中,會先構造一個Maxtrix臨時對象,然后銷毀
該臨時對象。
          函數func在(2)處調用+=操作符,該操作符返回一個Matrix對象
引用,因而不會構造臨時對象。
     準則
         對于類類型對象,使用復合賦值操作符(如使用‘+=’而不是‘+’和
=’)來避免編譯器生成再銷毀不必要的臨時對象。
 
注:個人認為這個準則有失準確。此例中,+=操作符不產生臨時對象的原因在于該操作符按引用返回對象而非按值返回對象。因此,準確的說法是,使用按引用或指針返回對象的函數來避免構造不必要的臨時對象。


 

 

B.4   newdelete操作符
     準則
        在必要時,實現類屬的newdelete操作符,從而提升管理動態內存
的速度和內存利用率。


 

 

B.5   全局對象的初始化
     注解
          全局對象初始化的順序依賴于編譯器的實現。但可以肯定的是,在同一個解釋單元其初始化順序和對象的聲明順序相同。
    示例
 
          文件1           文件2             文件3
 
          int a = f();    int b = f();      int f(void)
                                            {
                                                static int a = 0;
                                                return a++;
                                            }
        程序可能將a初始化為0,而b1,或者反過來。這依賴于編譯器如何選擇他們的初始化順序。
         如果將文件2中變量b的聲明移到文件1中,那么兩變量的初始化順序就隨即確定了,即:
          文件1           文件2             文件3
 
          int a = f();                      int f(void)
          int b = f();                      {
                                                static int a = 0;
                                                return a++;
                                            }
         這種情況下,a要先于b被初始化。
         避免編寫依賴于不同解釋單元內全局對象初始化順序的代碼。


 

 

C.    關于速度的準則
C.1   元素為類對象的數組中的newdelete
     注解
         聲明元素為類對象的數組時,編譯器會為該數組每一個元素調用構造
函數。在超出該數組的作用域范圍時,又會一一調用每個元素的析構函數。構造/析構可能占用超乎想象的時間,這在實時過程系統中是一個問題。
準則
    在對時間要求比較高的過程系統中,避免創建/銷毀大型的元素為類對象的數組。


 

 

C.2   循環體內的對象聲明
注解
         如果在循環體內聲明類變量,那么在循環的每次迭代時都需要構造并
析構該對象。這種構造并析構帶來的問題就是循環執行速度降低。
示例
          for (i = 0; i < 1000; i++)
          {
              FOO a;
              ...
          }
     準則
        在循環體外部聲明類類型變量,而避免在內部聲明。


 

 

D.    編寫只讀型代碼準則
D.1   ROM中的const對象
     注解
          通常,如果const對象具有如下一些屬性,則可以存儲在ROM中:
          -- 具有static存儲時長
          -- 由常量表達式初始化
          -- 是一個PODplain old data)類型對象
          POD類型對象具有如下屬性:
          -- 一個無屬性(scalar)類型(數字, 枚舉和指針) 
          -- 類/結構/聯合體中所有數據成員都是public訪問權限并且是
POD類型, 同時類中沒有用戶自定義的構造函數/析構函數,沒有基類和虛函數
          -- 所有元素都是POD類型的數組
      示例
          static const char lang[] = "EC++";
          class A {
              int a;
          public:
              A();
              ~A();
          };
          const A x;
 
          'lang'可能存儲于ROM中,而‘x’則不會。
      準則
          欲將對象存儲于ROM中,則將對象聲明為POD類型,并使用常量初始化該對象。


 

 

NOTE: The form of presentation used here, and several of the specific
guidelines, were inspired by the excellent book by Thomas Plum and
Dan Saks, 'C++ Programming Guidelines' (Plum Hall Inc., 1991).

 

posted on 2009-04-29 14:02 Wealth 閱讀(1862) 評論(0)  編輯 收藏 引用 所屬分類: C++Translation

<2009年4月>
2930311234
567891011
12131415161718
19202122232425
262728293012
3456789

導航

統計

常用鏈接

留言簿

隨筆分類(8)

隨筆檔案(8)

文章分類

Around Web

CoBlog

Develop Usage Link

搜索

最新評論

閱讀排行榜

評論排行榜

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            国产精品卡一卡二卡三| 亚洲国产专区| 精品成人国产| 激情亚洲网站| 黄色成人av在线| 国产综合av| 亚洲国产成人在线视频| 亚洲国产另类 国产精品国产免费| 伊人夜夜躁av伊人久久| 亚洲人成网站在线播| 在线视频免费在线观看一区二区| 亚洲一区二区三区免费在线观看| 亚洲综合社区| 老司机久久99久久精品播放免费| 亚洲丰满在线| 这里只有精品电影| 久久精品卡一| 欧美视频在线观看免费| 国产欧美日韩一区二区三区在线观看| 国产综合色精品一区二区三区| 亚洲国产欧美另类丝袜| 亚洲一区二区影院| 美女国产精品| 亚洲午夜激情网站| 美日韩在线观看| 国产精品另类一区| 在线观看久久av| 亚洲免费一在线| 亚洲第一福利社区| 午夜精品一区二区三区电影天堂| 欧美在线资源| 亚洲激情二区| 午夜精品久久| 欧美刺激午夜性久久久久久久| 国产精品美女久久久久久久| 在线精品视频一区二区| 欧美一区1区三区3区公司| 亚洲电影av在线| 午夜精品久久| 国产精品久久久一区二区三区| 最新国产成人av网站网址麻豆| 亚洲欧美在线高清| 亚洲乱码日产精品bd| 久久综合久色欧美综合狠狠| 久久人人爽人人爽| 日韩小视频在线观看专区| 久久精品人人做人人爽| 亚洲理伦在线| 久久亚洲色图| 永久久久久久| 老司机aⅴ在线精品导航| 欧美一区二区视频观看视频| 国产精品色一区二区三区| 亚洲天堂久久| 一本久久精品一区二区| 欧美日韩成人一区| 一区二区精品在线| 亚洲精品日产精品乱码不卡| 欧美精品国产| 一区二区三区四区蜜桃| 亚洲精选久久| 欧美日韩福利视频| 一区二区日韩伦理片| 亚洲伦理中文字幕| 欧美视频精品一区| 亚洲午夜久久久久久久久电影网| 亚洲日本aⅴ片在线观看香蕉| 欧美大尺度在线观看| 99这里只有久久精品视频| 亚洲欧洲一区二区三区在线观看| 女仆av观看一区| 一区二区三区四区精品| 一本色道久久综合狠狠躁篇怎么玩| 欧美日韩一区二区三区免费| 亚洲伊人网站| 欧美影院精品一区| 亚洲激情啪啪| 亚洲视频香蕉人妖| 国产一区二区三区电影在线观看| 米奇777在线欧美播放| 欧美激情视频在线播放| 亚洲影院污污.| 欧美综合国产精品久久丁香| 亚洲精品美女在线观看播放| 亚洲私拍自拍| 今天的高清视频免费播放成人| 另类成人小视频在线| 欧美激情91| 午夜精品婷婷| 免费欧美在线| 欧美在线网站| 欧美国产日本韩| 欧美一级网站| 欧美高清在线精品一区| 香蕉久久夜色| 嫩草影视亚洲| 欧美在线关看| 欧美激情一区在线| 欧美影院视频| 欧美精品系列| 久久亚洲精品网站| 欧美午夜电影在线| 欧美成人中文字幕在线| 国产精品videosex极品| 欧美a级片网站| 国产麻豆日韩| 亚洲精品一区二| 伊人男人综合视频网| 久久精品国产亚洲精品 | 99视频一区二区| 久久久久久久久久久成人| 日韩视频免费看| 国产裸体写真av一区二区| 欧美日韩小视频| 欧美激情国产日韩| 久久久久久自在自线| 欧美一区二区三区另类| 亚洲一二三四区| 国产精品一区二区久激情瑜伽| 午夜精品久久久久久久99热浪潮 | 国产亚洲一区二区在线观看| 欧美国产精品日韩| 欧美大片在线看| 欧美精品二区| 欧美极品一区二区三区| 欧美日韩你懂的| 国产精品久久久久久久久久尿| 欧美国产成人精品| 国产精品扒开腿爽爽爽视频| 国产欧美精品日韩区二区麻豆天美| 国产精品一区二区三区成人| 国产精品一级| 在线成人激情黄色| 一本久久综合亚洲鲁鲁| 久久激情中文| 99re6这里只有精品| 欧美一区二区在线看| 欧美粗暴jizz性欧美20| 国产免费成人| 亚洲一区二区三区四区五区午夜| 欧美自拍偷拍| 亚洲免费观看在线视频| 久久深夜福利免费观看| 国产精品视频久久一区| 亚洲国产综合在线看不卡| 欧美高清视频| 国产自产2019最新不卡| 亚洲另类在线一区| 蜜臀久久久99精品久久久久久| 亚洲蜜桃精久久久久久久| 久久久中精品2020中文| 国内伊人久久久久久网站视频| 亚洲性线免费观看视频成熟| 亚洲国产日韩欧美在线99| 欧美综合国产| 精品不卡一区| 久久综合久色欧美综合狠狠| 午夜精品在线视频| 国产一区高清视频| 久久久国际精品| 久久av二区| 亚洲福利精品| 亚洲精品网址在线观看| 欧美日韩中文字幕精品| 性高湖久久久久久久久| 欧美一区二区视频97| 亚洲第一区色| 亚洲一区二区伦理| 一区一区视频| 亚洲老司机av| 国产丝袜美腿一区二区三区| 嫩草国产精品入口| 欧美日韩少妇| 免费一级欧美片在线播放| 欧美久久成人| 久久综合久久综合九色| 欧美日韩亚洲一区二区三区在线观看| 午夜在线一区| 免费一级欧美片在线播放| 亚洲欧美日韩在线不卡| 久久久久久久久岛国免费| 亚洲影院高清在线| 欧美www在线| 久久综合色综合88| 国产欧美日韩中文字幕在线| 亚洲福利视频网站| 国产一区999| 午夜视频在线观看一区二区三区| 亚洲国产小视频在线观看| 欧美一区二区三区四区在线观看| 9色精品在线| 久久躁日日躁aaaaxxxx| 欧美日韩一区二| 99re在线精品| 亚洲一区二区三区国产| 欧美日本一道本| 最新69国产成人精品视频免费| 亚洲国产欧美一区二区三区同亚洲 | 欧美日韩精品一区二区三区| 欧美高清视频一区二区三区在线观看 |