Going from C to C++

Instead of “typedef” use “using”

Show More

    From “https://www.nextptr.com/tutorial/ta1193988140/how-cplusplus-using-or-aliasdeclaration-is-better-than-typedef” :

    
    
    1
    2
    3
    4
    5
    <span class="com">// create an alias of reference to int[4];</span>
    <span class="kwd">using</span> <span class="typ">IntArray4</span> <span class="pun">=</span> <span class="kwd">int</span><span class="pun">(&amp;)[</span><span class="lit">4</span><span class="pun">];</span>

    <span class="com">// or with typedef</span>
    <span class="com">// typedef int(&amp;IntArray4)[4];</span>

    When it comes to defining simpler type aliases, choosing between typedef and alias-declaration could be a matter of personal choice. However, while defining the more complex template aliases, function-pointer aliases, and array reference aliases, the alias-declaration is a clear winner.

    Instead of “#define” use “const”

    Show More

    From : https://root.cern.ch/TaligentDocs/TaligentOnline/DocumentRoot/1.0/Docs/books/WM/WM_92.html

    Never use #define symbolic constants Instead, use the C++ const storage class. As with #define symbols, const declarations are evaluated at compile time (for types and expressions that qualify as compile-time constants). Unlike #define symbols, they follow the C scope rules and have types associated with them. You can also use enum to prevent a host of problems. For example:

    #define kGreen 1 // Bad const int kGreen = 1; // Better enum Color {kRed, kGreen, kBlue} // Best

    If you accidentally redefine a name with a #define, the compiler silently changes the meaning of your program. With const or enum you get an error message. Even better, with enum you can put the identifiers in the scope of a class. As an added bonus, each enumeration is treated as a separate type for purposes of type checking (much like the way scalars are handled in Pascal) and for purposes of overloading.

    Unlike in ANSI C, objects in C++ that are declared const and initialized with compile-time expressions are themselves compile-time constants (but only if they are of integral or enumeration type). Thus, they can be used as case labels or in compile-time expressions.

    Use auto whenever possible

    https://subscription.packtpub.com/book/application_development/9781786465184/1/ch01lvl1sec5/using-auto-whenever-possible

    Use C++ cast instead of C casting

    int f = (int) test; vs static_cast<int>(test) –  See http://www.cplusplus.com/doc/oldtutorial/typecasting/

    Use std::string instead of char array

    1
    std::string

     instead of character arrays

    Use the Standard Template Library containers

    Migrate from hand-crafted containers to C++ Standard Template Library containers

    Use Nullptr instead of Null

    Use Namespaces

    Here is a blog about why ;https://cppdepend.com/blog/?p=79

    
    
    1
    2
    3
    4
    <var>namespace</var> myNamespace
    {
      <var>int</var> a, b;
    }

     

    Use reference instead of pointer for parameters to functions

    Reference can’t be NULL, so you don’t be accident de-reference a NULL pointer.

     

    Use ++i instead of i++

    You should prefer pre-increment operator (++iter) to post-increment operator (iter++) if you are not going to use the old value. Avoids copy of value

    Scoped Enumerations

    From : https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#example-149 – To minimize surprises: traditional enums convert to int too readily.

    
    
    1
    2
    3
    4
    void Print_color(int color);

    enum Web_color { red = 0xFF0000, green = 0x00FF00, blue = 0x0000FF };
    enum Product_info { red = 0, purple = 1, blue = 2 };

    Use Enum Class

    
    
    1
    2
     <span class="kwd">enum</span> <span class="kwd">class</span> <span class="typ">Color</span> <span class="pun">{</span><span class="pln"> red</span><span class="pun">,</span><span class="pln"> green</span><span class="pun">,</span><span class="pln"> blue </span><span class="pun">};</span> <span class="com">// enum class</span>
     <span class="kwd">enum</span> <span class="typ">Animal</span> <span class="pun">{</span><span class="pln"> dog</span><span class="pun">,</span><span class="pln"> cat</span><span class="pun">,</span><span class="pln"> bird</span><span class="pun">,</span><span class="pln"> human </span><span class="pun">};</span> <span class="com">// plain enum </span>

    What is the difference between two?

    • 1
      enum class

      es – enumerator names are local to the enum and their values do not implicitly convert to other types (like another 

      1
      enum

       or 

      1
      int

      )

    • Plain 
      1
      enum

      s – where enumerator names are in the same scope as the enum and their values implicitly convert to integers and other types

     

    Prefer compile-time checking to run-time checking

    Reason

    Code clarity and performance. You don’t need to write error handlers for errors caught at compile time.

    
    
    1
    2
    // Int is an alias used for integers
    static_assert(sizeof(Int) &gt;= 4);    // do: compile-time check

     

    P.8: Don’t leak any resources

    Prefer RAII (Clean up in the destructor)

    I.4: Make interfaces precisely and strongly typed

    Reason

    Types are the simplest and best documentation, improve legibility due to their well-defined meaning, and are checked at compile time. Also, precisely typed code is often optimized better.

    Example bad:

    
    
    1
    set_settings(true, false, 42); // what do the numbers specify?

    Example Good:’

    
    
    1
    2
    3
    4
    s.enabled     = true;
    s.displayMode = false;
    s.frequency   = 100;
    set_settings(s);

    I.23: Keep the number of function arguments low

    Reason

    Having many arguments opens opportunities for confusion. Passing lots of arguments is often costly compared to alternatives.

     

    F.2: A function should perform a single logical operation

    Reason

    A function that performs a single operation is simpler to understand, test, and reuse.

    F.3: Keep functions short and simple

    Reason

    Large functions are hard to read, more likely to contain complex code, and more likely to have variables in larger than minimal scopes. Functions with complex control structures are more likely to be long and more likely to hide logical errors

    F.4: If a function may have to be evaluated at compile time, declare it constexpr

    Show More

    Reason

    constexpr is needed to tell the compiler to allow compile-time evaluation.

    Example

    The (in)famous factorial:

    
    
    1
    2
    3
    4
    5
    6
    7
    8
    constexpr int fac(int n)
    {
        constexpr int max_exp = 17;      // constexpr enables max_exp to be used in Expects
        Expects(0 &lt;= n &amp;&amp; n &lt; max_exp);  // prevent silliness and overflow
        int x = 1;
        for (int i = 2; i &lt;= n; ++i) x *= i;
        return x;
    }