• <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>

            [翻譯]嵌入式C++編程準(zhǔn)則

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


             

             

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

            A1     字符常量

                          注解

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

             

                          示例

                                 I = sizeof(‘a’);

             

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

                         

                          準(zhǔn)則

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


             

             

            A2     文件范圍內(nèi)的對象聲明

                          注解

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

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

             

            示例

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

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

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

             

                          準(zhǔn)則

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

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


             

             

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


             

             

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


             

             

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


             

             

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


             

             

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


             

             

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


             

             

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


             

             

            A.10 C++增加的關(guān)鍵字
                 注解
                      C中沒有下面的C++關(guān)鍵字:
                      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;

                     準(zhǔn)則

                               確保沒有使用C++關(guān)鍵字作為標(biāo)記符。


             

             

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


             

             

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


             

             

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

             


             

             

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


             

             

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


             

             

            B.3   返回值中的臨時對象
                 注解
                     函數(shù)按值返回一個對象時,可能需要創(chuàng)建并銷毀一個臨時對象,從而
            導(dǎo)致代碼量增加并且?guī)磉\(yùn)行時開銷。
             示例
                      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)
                      }
                      函數(shù)func在(1)處調(diào)用了+操作符,該操作符按值返回一個Matrix
            對象。在某些編譯器實(shí)現(xiàn)中,會先構(gòu)造一個Maxtrix臨時對象,然后銷毀
            該臨時對象。
                      函數(shù)func在(2)處調(diào)用+=操作符,該操作符返回一個Matrix對象
            引用,因而不會構(gòu)造臨時對象。
                 準(zhǔn)則
                     對于類類型對象,使用復(fù)合賦值操作符(如使用‘+=’而不是‘+’和
            =’)來避免編譯器生成再銷毀不必要的臨時對象。
             
            注:個人認(rèn)為這個準(zhǔn)則有失準(zhǔn)確。此例中,+=操作符不產(chǎn)生臨時對象的原因在于該操作符按引用返回對象而非按值返回對象。因此,準(zhǔn)確的說法是,使用按引用或指針返回對象的函數(shù)來避免構(gòu)造不必要的臨時對象。


             

             

            B.4   newdelete操作符
                 準(zhǔn)則
                    在必要時,實(shí)現(xiàn)類屬的newdelete操作符,從而提升管理動態(tài)內(nèi)存
            的速度和內(nèi)存利用率。


             

             

            B.5   全局對象的初始化
                 注解
                      全局對象初始化的順序依賴于編譯器的實(shí)現(xiàn)。但可以肯定的是,在同一個解釋單元其初始化順序和對象的聲明順序相同。
                示例
             
                      文件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被初始化。
                     避免編寫依賴于不同解釋單元內(nèi)全局對象初始化順序的代碼。


             

             

            C.    關(guān)于速度的準(zhǔn)則
            C.1   元素為類對象的數(shù)組中的newdelete
                 注解
                     聲明元素為類對象的數(shù)組時,編譯器會為該數(shù)組每一個元素調(diào)用構(gòu)造
            函數(shù)。在超出該數(shù)組的作用域范圍時,又會一一調(diào)用每個元素的析構(gòu)函數(shù)。構(gòu)造/析構(gòu)可能占用超乎想象的時間,這在實(shí)時過程系統(tǒng)中是一個問題。
            準(zhǔn)則
                在對時間要求比較高的過程系統(tǒng)中,避免創(chuàng)建/銷毀大型的元素為類對象的數(shù)組。


             

             

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


             

             

            D.    編寫只讀型代碼準(zhǔn)則
            D.1   ROM中的const對象
                 注解
                      通常,如果const對象具有如下一些屬性,則可以存儲在ROM中:
                      -- 具有static存儲時長
                      -- 由常量表達(dá)式初始化
                      -- 是一個PODplain old data)類型對象
                      POD類型對象具有如下屬性:
                      -- 一個無屬性(scalar)類型(數(shù)字, 枚舉和指針) 
                      -- 類/結(jié)構(gòu)/聯(lián)合體中所有數(shù)據(jù)成員都是public訪問權(quán)限并且是
            POD類型, 同時類中沒有用戶自定義的構(gòu)造函數(shù)/析構(gòu)函數(shù),沒有基類和虛函數(shù)
                      -- 所有元素都是POD類型的數(shù)組
                  示例
                      static const char lang[] = "EC++";
                      class A {
                          int a;
                      public:
                          A();
                          ~A();
                      };
                      const A x;
             
                      'lang'可能存儲于ROM中,而‘x’則不會。
                  準(zhǔn)則
                      欲將對象存儲于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 閱讀(1857) 評論(0)  編輯 收藏 引用 所屬分類: C++ 、Translation

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

            導(dǎo)航

            統(tǒng)計(jì)

            常用鏈接

            留言簿

            隨筆分類(8)

            隨筆檔案(8)

            文章分類

            Around Web

            CoBlog

            Develop Usage Link

            搜索

            最新評論

            閱讀排行榜

            評論排行榜

            欧美精品丝袜久久久中文字幕 | 久久综合88熟人妻| 亚洲中文字幕久久精品无码APP| 亚洲国产一成人久久精品| 久久午夜电影网| 思思久久99热只有频精品66| 久久精品国产亚洲AV无码麻豆| 国产69精品久久久久99| 婷婷久久五月天| 欧美亚洲另类久久综合| 久久精品国产清自在天天线| 久久婷婷综合中文字幕| 久久久久亚洲AV无码网站| 日日狠狠久久偷偷色综合96蜜桃| 日产精品久久久一区二区| 青青久久精品国产免费看| 久久国产免费观看精品3| 久久99国产精品久久99小说| 久久99国产亚洲高清观看首页| 久久久久亚洲AV成人网人人网站| 久久本道伊人久久| 久久精品九九亚洲精品| 久久精品中文字幕一区| 久久免费视频一区| 久久99精品国产99久久6| 青青青国产精品国产精品久久久久| 久久精品国产清自在天天线| 久久99九九国产免费看小说| 亚洲欧美成人久久综合中文网| 久久久久无码精品国产app| 99久久国产综合精品成人影院| 久久婷婷国产麻豆91天堂| 久久99国产精品二区不卡| 九九久久99综合一区二区| 热99re久久国超精品首页| 国产成人精品综合久久久| 国产精品免费福利久久| 久久免费线看线看| 久久久无码精品午夜| 大香伊人久久精品一区二区| 伊人久久大香线蕉亚洲|