Clause 02: Try to replace the #define with Const,enum,inline
#define PI 3.14
1) for such a macro definition, pi before the compilation by the preprocessor all replaced by 3.14, so pi may not enter the symbol table, when the use of this constant compile error, error message may refer to 3.14 instead of PI, Programmers who do not know this macro definition can be confusing at this time.
The workaround is to use the const:
Const Dobule Pi = 3.14;
2) Second, defining a bad macro can make people miserable. For example:
#define MAX (A, b) a > B? A:b
The seemingly correct wording is flawed, such as our use of:
int a = 1, b = 3, c;c = ++max (A, b);
The intention is to assign the result of the maximum value plus 1 in a and B to C, after the actual preprocessing, the code becomes:
c = + + a > B? A:B;
The final result of C is 3, not the 4 we want.
So remember to give all the actual in the macro to join the parentheses!!! Such as:
#define MAX (A, B) ((a) > (b))? (a): (b))
That being the case, there are still some unexpected problems.
Like what:
int a = 5, B = 0;max (++a, b),//a is incremented two times Max (++a, B +);//a is added once
The cumulative number of a is determined by "who is it to compare with".
At this point, you need inline to resolve this issue:
Template <typename t>inline t max (const &t A, const &t b) //Because we don't know what T is, so pass by Reference-to-const { return (a > B? a:b);}
3) Using #define cannot define a constant or function that belongs to a class, but using const and inline can do so.
Please remember:
1) For simple variables, it is best to replace the #define with a const object or an enum;
2) for macros that resemble functions, it is best to replace the #define with the inline function instead.
Clause 03: Use const whenever possible
The keyword const can specify a value that should not be altered, and the compiler enforces this constraint.
If the keyword const appears to the left of the asterisk, indicating that the object is constant, and if it appears to the right of the asterisk, the pointer itself is a constant, and if it appears on both sides of the asterisk, both the finger and the pointer are constants.
Also pay attention to the const use of iterators:
Const Std::vector<int>::iterator ITER; Like T *const, the iterator itself cannot change std::vector<int>::const_iterator iter; Like a const T *, the contents of the iterator are unchanged
A fact many people disregard: two member functions can be overloaded if they are only constant (constness). This is also an important feature of C + +.
#include <iostream>using namespace Std;class textblock{public:textblock (string _str) {str = _STR;} Const char& operator[] (size_t pos) const //operator[] for const object {return Str[pos];} char& operator[] (size_t POS) //operator[] for Non-const object {return str[pos];} Private:string str;}; int main () {const class TextBlock CTB ("Hello"), class TextBlock TB ("World"), cout << ctb[0] << Endl; cout << tb[0] << endl;cin >> tb[0]; Because it is non-const, can also cincout << tb[0] << endl;return 0;}
However, the Non-const object can call the const operator[], in turn the Const object cannot call Non-const operator[] (can comment out the non-const operator[above) and try ^_^). Because const operator[] guarantees that the function does not modify the member variables of the object, Non-const operator[] cannot be guaranteed. Given that the const operator[] has completely done everything that non-const operator[] should do, the only difference is that the return type is more of a const modifier, in which case it is safe to remove the const, so we can use Non-const Opera Tor[] Call Const operator[] to avoid duplication of code.
The procedure is as follows:
Class Textblock{public:textblock (String _str) {str = _STR;} Const char& operator[] (size_t pos) const //operator[] for const object {return Str[pos];} char& operator[] (size_t POS) //operator[] for Non-const object {returnconst_cast<char&> (static_cast <const textblock&> (*this) //Use static_cast to cast the current object (*this) to the [POS] //const type and then call Const operator[], Last use); Const_cast removes the Const property of the return value from}private:string str;};
Please remember:
1) Declaring something as const can help the compiler detect incorrect usage. Const can be applied to objects within any scope, function arguments, function return types, member function ontologies;
2) The compiler enforces bitwise constness, but you should use "Conceptual constants" (conceptual constness) to write programs;
3) when the const and NON-CONST member functions have a substantially equivalent implementation, making the NON-CONST version call the const version avoids code duplication.
Article 04: Determine that the object was initialized before it was used
Always remember this: reading an uninitialized value can cause ambiguous behavior. Always initialize the object before it is used.
1) for the built-in type, it must be initialized manually;
2) for something other than the built-in type, the initialization responsibility is on the constructor, to ensure that each constructor initializes each member of the object.
When initializing with constructors, remember the difference between initialization (initialization) and assignment (Assignment).
Where the constructor is initialized in the member initialization list, the function body is not initialized, but is assigned, so for members that do not use the list initialization, the compiler automatically calls its corresponding default constructor, and then assigns the new value to the function body immediately after entering it.
Given that member variables like const or reference must be initialized and cannot be assigned, it is best to always use the member initialization list.
For example:
#include <iostream>using namespace Std;class textblock{public:textblock (const int &_a, int &_b): A (_a), B ( _b) {} //Note that the parameter referenced here uses int &, and if you use const int&private: //Then our member variable must also be a constant reference, otherwise an error. const INT A;int &b;}; int main () {int i = 1, j = 2;class TextBlock TB (i, j); return 0;}
When I want to put the "initialize" process in the function body, the GCC error is as follows:
error:uninitialized member ' textblock::a ' with ' const ' type ' const int ' [-fpermissive]error:uninitialized reference memb Er ' textblock::b ' [-fpermissive]
Once again, only the member initialization list is where the member is actually initialized, and the function body is only assigned.
Please remember:
1) manual initialization of the built-in objects, because C + + does not guarantee that they are initialized. ;
2) constructors are best used with member initialization lists (member initialization list) instead of using assignment operations (Assignment) in the constructor body. The sort order of the initialization list is best consistent with the order in which they are declared in class;
3) in order to exempt the "initialization Order of cross-compilation units" issue, replace the non-local static object with the local static object.
"Effective C + + reading notes" Article II (clause 02~ clause 04)