"Effective C + + reading notes" (i)

Source: Internet
Author: User

"Effective C + + reading notes" clause 01: C + + as a language federal

Consider C + + as a federation, not a single language, that is made up of related languages.

We can consider C + + as a four-part:

1. C language. C + + blocks, statements, pre-processor, built-in data types, arrays, pointers, etc. all come from the C language.

2. Object-oriented C + +. Classes (including constructors and destructors), encapsulation, inheritance, polymorphism, virtual functions (dynamic binding) ... Wait a minute. This section is designed for object-oriented purposes.

3. Template C + +. This is part of C + + generic programming.

4. STL. STL is a template library that contains containers, iterators, algorithms, and function objects.


The code for efficient programming of C + + varies depending on what part of C + + you use.


"Effective C + + reading notes" clause 02: Try to substitute const, enum, inline instead of #define

1. Use const to define constants instead of #define define constants, because using the const compiler can better help you

Like #define Aspect_ratio 1.653.

Because #define replace Aspect_ratio with 1.653 in the preprocessing phase, the compiler has never seen aspect_ratio this symbol

When a compile error occurs because of this constant, we can only get relevant information about 1.653, if you have no idea of the number 1.653 or the constant is from someone else's header file, then you will not be able to debug it.

Therefore we should take advantage of the const double aspectratio = 1.653;

In this case, you can avoid this happening.

2. Class-specific constants should be defined as static const

Not using # define is because # define does not value the scope, so it cannot be used to define the class's own constants, nor can it be used to provide any encapsulation, meaning that #define cannot have a private property

The reason to use static is to have the entire class share an entity, rather than having one entity per object


Also note the initialization of the static object class gameplayer{private:static const int Num = 5;//Here is a variable that declares a static const type                                                                //part of the compiler, which allows only integral types  Static constants in the class initialize//Even some of the static constants of the compiler's integral type do not work int score[num];.};//defines class-specific constants, and if they are not initialized within the class, they need to be assigned an initial value and cannot be marked as static const int gameplayer::num;

3. Constants can be defined with enum

As mentioned in the comments above, some compilers do not even allow integer static constants to be initialized within a class, so you cannot initialize an array within the class with this static constant (because the compiler must know the size of the array at compile time)

PS: The above parentheses are directly transcription, so that initializing static constants outside of the class is done at run time? Do not understand ah, too weak ah, beg to pass by the great God help answer under AH

So we can use enum instead.

Then the above class can be changed to the following: Class gameplayer{private:enum{Num =  5}; int score[num]; ...};

and Enum wants to #define more than const, like # define, can't take an address, can't use a reference or a pointer to it

4. Replace #define macro with inline

First, let's look at the drawbacks of #define defined macros



This is a macro that asks for the maximum value
First, the macro will be less efficient in some cases, assuming there is a complex function f (int) that is more complicated (may run longer);

Then you can use MAX (f (1), F (2)) efficiency directly.

Second, it is easy to cause unexpected problems
For example:

int a = 5, b = 0; MAX (+ + A, b); A has since added two times max (+ A, B + 10); A has since been added once

This uncertainty is obviously not what we want.
of course, there are some situations, such as the parentheses are not careful and so on, it is possible because of operator precedence and the like to get baffled results.


So, there are a lot of flaws in using # define to implement macros, and we should use the inline function instead

For this feature where # define is type-independent, you can use a template function to implement templates <typename t> inline T (Const T & A, const T & B) {return a < ; B? A:B;}

Similarly, you cannot use a #define to implement the private function of class, and you can use inline to


Please remember:

For simple constants, it is best to replace #define with const objects or enums

For macros that resemble functions, it is best to use the inline function instead of # define



"Effective C + + reading notes" clause 03: Use const whenever possible

The keyword const has a lot to do, and you can use her to modify the constants in the global or namespace scope outside of the classes, or to decorate a file, function, or object declared static in the scope of a chunk. You can also indicate that the pointer itself, the pointer, or both (or neither) are const.

Char greeting[] = "Hello"; char * p = greeting;//non-const pointer, non-const dataconst char * p = greeting;//Non-con St pointer, const DATACHAR * Const P = greeting;//const pointer, non-const dataconst char * const p = greeting;//con St Pointer, const data

If the const appears on the right side, then the pointer itself is a constant, if the const appears to the left of the pointer, indicating that the pointer is a constant


The most powerful usage of const is the application at the time of function declaration. Within a function declaration, a const can be associated with a function return value, each parameter, the function itself (if it is a member function) .


Use const to modify function return value

If the return value of a function is not likely to be an lvalue, we can set the return value of the function to const to reduce the chance of generating an error (or the compiler can help you if it is careless)

Like what:

Class Rational {...}; const RATIONAL operator * (const rational & LHS, const rational & RHS);

do not return a const word, such code can also be compiled through the

Rational A, B, C;.. (A * b) = C;

but it is not necessary for us to assign the result of a * B, because the result of a * b is a temporary variable, even if it is not useful to assign a value

Actually just want to compare, missing an equal sign

If your return value is const, then the behavior of the manual compiler will help you find it.

Otherwise... Slow down.


Const member functions

The use of a const member function is based on two reasons:

The first is that they are class interfaces that are relatively easy to understand. Because it is easier to know that the function can change the object content and which function is not.

The second is that it can be used to manipulate const objects, such as the following example

Class Point{public:P oint (): A (0), B (0) {}point (int _a, int _b): A (_a), B (_b) {}int Geta () const {return A;} Private:int A, b;}; int main () {const point A (1, 2); A.geta (); return 0;}
If the Geta is not const-modified, a compile error will occur for the constant const point

And we usually can not avoid the operation of the constant object, such as the function when the parameter is often passed the const T &, if passed in even a get function can not be used, then pass an egg

So if you're sure that this function doesn't change the object's member variables, then use the const modifier.


Avoid duplication in const and NON-CONST member functions


The other two member functions can be overloaded only if they are of a constant nature, such as:

Class Textblock{public:. Const char & operator[] (std::size_t position) <span style= "color: #FF0000;" ><strong>const </strong></span>{...//boundary check ...//log data Access ...//test data integrity return text[position];} Char & operator[] (std::size_t position) {...//boundary check ...//log data Access ...//Verify data integrity return text[position];};
so the overloads of the two functions are possible


And then the problem comes again, where the two functions are basically the same, and the duplicate code is awful.

Here is a better way to solve this problem, use Non-const operator[] to call its const version, the code is as follows:

Class Textblock{public: ... const char & operator[] (std::size_t position) const {...//boundary check ...//log data Access ...//test data complete Integer return text[position];} Char & operator[] (std::size_t position) {return const_cast<char&> (Static_cast<const textblock&& gt; (*this) [postion]);};
Two conversions are done here, first using static_cast (this), which is the object that the object is converted to const, and then called operator[]. This is called the const version of operator [], and after the call is finished, use Const_cast to remove the const attribute of the returned const char&.

Please remember:

1. Declaring something as const can help the compiler detect incorrect usage. Const can be applied to any scope object, function arguments, function return type, member function ontology.
2. The compiler enforces bitwise constness, but you should use "Conceptual constants" (conceptual constness) when you 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


"Effective C + + reading notes" clause 04: Determining that an object was initialized before being used

C + + seems capricious with regard to initializing objects. For example, for built-in variables, defined in the heap memory, is initialized, defined in the stack memory will not be initialized.

In short, "when an object's initialization action must occur and when it does not necessarily occur" is a very complex rule, then the best way is to always remember to initialize before using


Initialization of built-in data types

Can only be manually initialized, such as:

int x = 0;                             The int type initializes the const char * text = "Hello world";//manual initialization of the pointer double D;//Initialize CIN >> D with input;

initialization of objects (with constructors)

The rule is simple: make sure that each member of the object is initialized by a constructor.


First, we should distinguish between initialization and assignment.

Class People{public:P eople () {}people (string _name, int _age);p rivate:string name; int age;};/ /This form is initialized people::P eople (string _name, int _age): Name (_name), age (_age) {}//This form is assigned the initial value people::P eople (String _name, int _age) {       name = _name;//This is just an assignment, the parentheses begin to indicate that initialization is over, here is doing some initialization work after age = _age;}

The first way is more efficient, call the constructor directly, and the second method calls the assignment constructor

C + + members are initialized in the following order: The base class object is initialized first, then the member variable of the derived class, and the member variables of the derived class are initialized in the same order as the declaration order


Initialization of non-local static objects defined in different compilation units

The so-called static object whose lifetime is constructed from the end of the program so that both the stack and the Heap-based object are excluded. Such objects include global objects, objects defined within the namespace scope, within classes, within functions, and objects declared as static within the file scope. The static objects inside the function are called local static objects (because they are local to the function), and other static objects are called non-local static objects. The static objects are automatically destroyed at the end of the program, i.e. their destructors are automatically called at the end of Main ().

The problem is that there is a non-non-local static object in all two compilation units, and one object must be used to initialize the other object, so that the compiler cannot control its sequencing.


from the code above, it is possible for the Directory object to initialize successfully, depending on whether TFS has been initialized

Therefore, we can use a single-piece mode, the specific operation is to convert TFS and temp Dir to the local static object, change to the following

Filesystem.cppclass filesystem{public: ... std::size_t numdisks () const;..}; FileSystem & TFS () {static FileSystem FS; return FS;} Directory.cppclass directory{public:D irectory () {... std::size_t disks = Tfs.numdisks (); ...} ... private:...std::size_t disks;};D Irectory & TempDir () {static Directory TD; Return TD;}


Please remember:
1. Manual initialization of built-in objects, because C + + does not guarantee that they are initialized.
2. Constructors are preferable to use the Member initial column (member initialization list) instead of using an assignment operation (assignment) within the constructor body. The initial Value column lists the member variables in the same order as 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" (i)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.