The Embedded C++ Programming Guide Lines

来源:互联网 发布:爱情动作片推荐 知乎 编辑:程序博客网 时间:2024/05/21 06:59

The Embedded C++ Programming Guide Lines

Version WP-GU-003,Copyright(C) 6,Jan 1998 by the Embedded C++ Technical Committee


Embedded C++ Programming GuideA.    Migrating from C language to C++ languageA.1   Character constant      Note          In C, a character constant has type int.  In C++, it has          type char.      Example          i = sizeof('a');          In C, this stores sizeof(int) (which is likely to be          greater than 1) into i.  In C++, it stores sizeof(char)          (which is always 1) into i.      Guideline          When migrating code from C to C++, rewrite expressions          that depend on the size of a character constant to remove          the dependency.A.2   Object declaration at file scope      Note          In C++, a declaration of an object at file scope without a          storage class specifier is a definition of that object          with external linkage.  If the definition does not have an          initializer, the object has initial value 0.  (As in C, an          object declared in a C++ program must be defined exactly          once.)          In C, a declaration of an object at file scope without a          storage class specifier and without an initializer is a          tentative definition, which may appear more than once in a          translation unit.      Example          int a;          /* (1) */          int a = 10;     /* (2) */          In C, (1) is a tentative definition.  Since (2) is          unequivocally a definition, C treats (1) as a mere          declaration.          In C++, both (1) and (2) are definitions.  In the          presence of (1), (2) is a duplicate definition, and          therefore an error.      Guideline          In C++, a declaration of an object at file scope is just a          declaration (and not also a definition) if and only if it          has an explicit extern specifier and no initializer.          Each object declared at file scope must be defined exactly          once.  All but one declaration must have both an explicit          extern specifier and no initializer.A.3   const type qualifier      Note          In C, a const-qualified object at file scope without an          explicit storage class specifier has external linkage.  In          C++, it has internal linkage.      Example          +- file1 --------------------+          |      extern const int n;   |          +----------------------------+          +- file2 --------------------+          |      const int n = 10;     |          +----------------------------+          In C, object n of file2 has external linkage, so it can          satisfy the reference to n (also with external linkage) in          file1.  In C++, object n in file2 has internal linkage,          and will not satisfy the reference to n in file1.      Guideline          Const-qualified objects with external linkage must have an          explicit extern specifier.A.4   Conversion to void *      Note          In C, there is a standard conversion from void * to T *          (for any object type T).  In C++, there is no such          conversion.  Such conversions require a cast in C++.          The following Standard C library functions return void *:              calloc, malloc, realloc, bsearch, memcpy, memmove,              memchr, memset          C++ requires an explicit cast when assigning the return          value of such a function to a pointer to non-void type.      Example          int* p;          p = malloc(10 * sizeof(int));          In C++, the assignment to p requires an explicit cast, as          in          p = (int *)malloc(10 * sizeof(int));      Guideline          In C++, use operator new instead of calloc, malloc, or          realloc.  (See item A.12).          Ignore the return value of a memcpy, memmove, and memset.          (They just return their first argument converted to void          *.)          For all other functions that return void * (standard or          user-defined), use an explicit cast when converting the          return value to another pointer type.A.5   Enumeration type      Note          In C, enumerations are integral types.  A program can          convert from an enumeration type to an integral type, and          back, without a cast.  A C program can apply ++ and -- to          an enumeration object.          In C++, each enumeration is a distinct type.  There are          standard conversions from enumeration type to integral          types, but not from integral types to enumeration types.          A C++ program cannot apply built-in ++ and --, nor any          compound assignment (such as +=) to an enumeration object.      Example          enum RGB { red, green, blue } rgb;          ++rgb;          ++rgb is an error in C++ if it uses the built-in ++          operator.  It means the same as          rgb = rgb + 1;          This is also an error unless you write it with a cast:          rgb = RGB(rgb + 1);          The best alternative is to implement an operator++ for          type RGB, as in          RBG &operator++(RGB &x)          {              return x = RGB(x + 1);          }      Guideline          When converting a C program to C++, provide typesafe          implementations for operator++ and operator-- as needed          for enumeration types.A.6   Type definition in cast, parameter declaration, or sizeof      Note          In C, types can be defined in a cast expression, parameter          declaration or sizeof expression.  In C++ they cannot.      Example          void func(struct TAG { int a; } st)          {              ...          }          Here, TAG is defined in the parameter declaration.      Guideline          Define a type used in a parameter declaration in the scope          enclosing the function declaration, or some larger          enclosing scope.          Define a type used in a cast expression or sizeof          expression in the scope enclosing the expression, or some          larger enclosing scope.A.7   Transfer of control past the definition of a local object      Note          In C, a goto or switch statement may transfer control          beyond the definition of an object at block scope,          possibly bypassing initialization.  In C++, it may not.      Example          goto LABEL;          {              int v = 0;              ...          LABEL:              ...          }          This is valid in C, assuming the code following LABEL:          does not depend on v being initialized to 0.  It is always          an error in C++.      Guideline          Do not use goto or switch statements to bypass          initialization of a local object.A.8   Character array initialization      Note          A C program can initialize an array of characters using a          string literal that defines one more character (counting          the terminating '/0') than the array can hold.          A C++ program cannot.      Example          char s[3] = "abc";          The size of the array is three, though the size of the          string literal is 4.  This is valid in C, but not C++.      Guideline          Do not initialize an array of characters using a string          literal with more characters (including the '/0') than the          array. Therefore, it is necessary to specify the correct size of           a string literal (char s[4] = "abc";).           However, because the result of the expectation always can be          obtained even if the size of the string literal is changed,          the method of not describing the size (char s[] = "abc";) is           recommended.A.9   Prototype declaration      Note          A C++ program requires that you declare a function          prototype before calling the function. In C, a call to          an undeclared function is permissible.  Moreover, a C++          program interprets the function declarator 'f()' as          equivalent to 'f(void)' -- a function with no arguments.          In C, the same declaration leaves the number and types          of the parameters unspecified.      Example          extern void func();          ....          sub();          func(0);          The call to function 'sub' is an error because there is no          prototype declaration.  The call to function 'func' is          also an error because its declaration says it has no          arguments.      Guideline          Always declare the prototype before calling a function.          To emphasize that function 'f' is called with no          arguments, write its declarator as 'f(void)'.A.10  Keywords added in C++      Note          The following C++ keywords are not keywords in 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      Example          int class, new, old;          This declaration is valid in C, but not in C++.      Guideline          Do not use a C++ keyword as an identifier.A.11  Scope of nested types      Note          In C, the name of a type defined inside a struct or union          is actually in same scope as the name of the enclosing          struct or union.  In C++, the name of the nested type is          within the scope of the enclosing struct or union.      Example          struct S {              int a;              struct T {                  int t;              } b;              int c;              enum E { V1, V2 } e;          };          struct T x;          enum E y;          The declarations for x and y are valid in C, but not in          C++.  In C++, the names T and E are not in scope outside          the definition of struct S.      Guideline          Do not define the name of a type as nested unless all uses          of that name are also in the scope of the enclosing          struct/union.A.12  Dynamic memory management      Note          There is no guarantee that new and delete apply the same          memory management policy to the same memory as do malloc          and free.  Therefore, a program cannot delete memory          unless that memory was previously acquired by new, and it          cannot free memory unless that memory was acquired by          malloc (or calloc or realloc).      Example          int (*p)[10];          p = (int (*)[10])malloc(sizeof(*p));          ....          delete p;          The delete expression has undefined behavior.      Guideline          In C++, avoid malloc, calloc, realloc and free; use only          new and delete.A.13  '/*' after '/'      Note          Writing the C-style comment '/* */' immediately after          the token '/' is interpreted as the C++-style comment          '//' instead.      Example          i = j //* comment */ k ;          The sequence '//' is interpreted as a comment delimiter.          The expression is interpreted not as 'i = j / k;' but as          'i = j'.      Guideline          Avoiding writing a C-style comment '/**/' immediately          after the token '/'.B.    Guidelines for Code SizeB.1   Object initialization      Note          There are various ways to specify the initialization of an          object.  Some initializations generate unnecessary          temporary objects, and result in larger code size.          For example:          T x(i)        // (1)          T x = i;      // (2)          T x = T(i)    // (3)          T x;          // (4)          x = i;        //          (1) This applies a constructor directly to object x              without using a temporary object, as if by calling:              x.T(i);             // apply constructor to x          (2) In some implementations, this applies a constructor              directly to x as above.  In others, it constructs a              temporary object, and initializes x from the              temporary, as if by calling:              temp.T(i);        // apply constructor to temp              x.T(temp);        // apply copy constructor to x              temp.~T();        // apply destructor to temp          (3) This is the same as (2).          (4) This initializes x using T's default constructor, then              later assigns a new value to x using an assignment              operator.  The assignment operator may release              resources that x is using and acquire new resources.              x.T();           // apply default constructor to x              x.operator=(i);  // apply assignment operator to x      Guideline          Use declarations of form (1) above in preference to the          other forms.B.2   Inline specifier      Note          Inline expansion reduces the overhead of function entry          and exit, but it may increase code size.          Member functions in class definitions are expanded inline          by default.      Guideline          Use inline specifier for only small functions.  A member          function for which inline expansion is not appropriate          should be defined outside the class definition, so that it          is not inline expanded.B.3   Temporary objects for return values      Note          Calling a Function that returns an object by value may          create and destroy a temporary object, thus increasing by          code size and execution time.      Example          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)          }          (1) calls operator+, which returns a Matrix by value.  In          some implementations this creates (and later destroys) a          temporary Matrix object.          (2) calls operator+=, which generates no temporary Matrix          objects.      Guideline          For objects of class types, use compound assignment          operators (such as += in preference to + and =) to avoid          creating and destroying temporary objects unnecessarily.B.4   Operators new and delete      Guideline          Implement class-specific operators new and delete as          needed to improve the speed and memory utilization of          dynamic memory management.B.5   Initialization of global objects      Note          The order of initialization of global objects is          implementation-dependent.  However, the order of          initialization in a single translation unit is guaranteed          to be the order of declaration.      Example          file1           file2             file3          int a = f();    int b = f();      int f(void)                                            {                                                static int a = 0;                                                return a++;                                            }          The program may initialize 'a' with 0 and 'b' with 1, or          vice versa, depending on the order the implementation          chooses to initialize them.          It is possible to make the initialization order well          defined by moving the declaration of 'b' in file2 to          file1, as in:          file1           file2             file3          int a = f();                      int f(void)          int b = f();                      {                                                static int a = 0;                                                return a++;                                            }          The order of initialization is a, then b.      Guideline          Avoid coding which depends on the initialization order of          global objects across translation units.C.    Guidelines for speedC.1   new and delete for array of class objects      Note          Declaration of an array of class objects calls its          element's constructor for each element.  The program calls          the destructor for each element when the array goes out of          scope.  The processing time of the constructor/destructor          may be unexpectedly long.  This can be a problem for          real-time processing.      Guideline          Avoid creating and destroying a large array of class          objects during time-critical processing.C.2   Object declaration in loops      Note          When a class variable is declared in a loop, its          constructor and destructor are called in each iteration.          The overhead of construction and destruction may slow the          loop.      Example          for (i = 0; i < 1000; i++)          {              FOO a;              ...          }      Guideline          Avoid declaring a class variable inside a loop.  Declare          it outside the loop instead.D.    Guidelines for ROMable codeD.1   const objects in ROM      Note          In general, a const-qualified object can reside in ROM if          it:          --  has static storage duration,          -- is initialized by a constant expression, and          --  has a POD (plain old data) type.          A POD type is any of:          --  a scalar (arithmetic, enumeration or pointer) type          --  a class, struct, or union all of whose data members              are public and of POD types, and with no user-defined              constructor or destructor, no base classes, and no              virtual functions          --  an array with elements of POD type      Example          static const char lang[] = "EC++";          class A {              int a;          public:              A();              ~A();          };          const A x;          'lang' may be placed in ROM; 'x' may not.      Guideline          Declare objects to be placed in ROM with POD types and          with constant initializers.NOTE: The form of presentation used here, and several of the specificguidelines, were inspired by the excellent book by Thomas Plum andDan Saks, 'C++ Programming Guidelines' (Plum Hall Inc., 1991).
原创粉丝点击