Const and # define

Source: Internet
Author: User

Try to use const and inline instead of # define

This clause is best referred to as "try to use the compiler instead of preprocessing", because # define is often considered not part of the language itself. This is one of the problems. Let's look at the following statement:

# Define aspect_ratio 1.653

The compiler will never see the aspect_ratio symbol name, because it will be removed by the Preprocessing Program before the Source Code enters the compiler, so aspect_ratio will not be added to the symbol list. If the Code involved in this constant encounters an error during compilation, it will be confusing, because the error message refers to 1.653 instead of aspect_ratio. If aspect_ratio is not defined in the header file you write, you may wonder where 1.653 came from and even take time to track it. This problem also occurs in the symbol debugger, because, similarly, the symbolic names you write will not appear in the symbol list.

The solution to this problem is simple: Define a constant without preprocessing macros:

Const double aspect_ratio = 1.653;

This method is very effective. But there are two special cases to note.
First, pointer constants are defined differently. Because constant definitions are generally placed in header files (many source files will contain them), apart from defining the types referred to by pointers as const, it is important that pointers are often defined as Const. For example, to define a char *-Based String constant in the header file, you need to write the const twice:

Const char * const authorname = "Scott Meyers ";

For more information about the meaning and usage of const, especially the issues related to pointers, see section 21.

In addition, defining constants of a class is also very convenient, with only a little difference. To restrict a constant to a class, you must first make it a member of the class. To ensure that a constant has only one copy at most, you must define it as a static member:

Class gameplayer {
PRIVATE:
Static const int num_turns = 5; // constant eclaration
Int scores [num_turns]; // use of constant
...
};

Also, as you can see, the preceding statement is the num_turns statement, rather than the definition. Therefore, you must define static members of the class in the implementation code file of the class:

Const int gameplayer: num_turns; // mandatory definition;
// Goes in class impl. File

You don't have to worry too much about such things. If you forget the definition, the linker will remind you.

The old compiler does not accept this syntax because it deems that the static member of the class is illegal to define the initial value during declaration. Moreover, only the integer type can be initialized in the class (such as: int, bool, Char, etc.), and can only be constants.

When the preceding syntax is not available, you can assign an initial value during definition:

Class engineeringconstants {// This goes in the class
PRIVATE: // header file
Static const double fudge_factor;
...
};
// This goes in the class implementation file
Const double engineeringconstants: fudge_factor = 1.35;

In most cases, you only need to do so much. The only exception is when your class needs to use the constants of this class during compilation, such as the above gameplayer :: scores array declaration (the compiler must know the size of the array during compilation ). Therefore, in order to make up for the deficiencies in the compilers that (incorrectly) Disable class constant initialization, you can use the method called "borrow Enum" to solve the problem. This technique makes good use of the enumeration type principle when int type is required, so gameplayer can also be defined as follows:

Class gameplayer {
PRIVATE:
Enum {num_turns = 5} // "The Enum hack"-makes
// Num_turns a symbolic name
// For 5
Int scores [num_turns]; // fine
};

Unless you are using an old Compiler (that is, before 1995), you do not have to borrow enum. Of course, it is worthwhile to know this method, because the code that can be traced back to a long time ago is not common.

Return to the topic of preprocessing. Another common # define command is to use it to implement macros that look like a function and will not cause function calls. A typical example is to calculate the maximum values of two objects:

# Define max (A, B) (a)> (B )? (A): (B ))

This statement has many defects. It is even more painful to think about it than to drive on the highway during peak hours.
No matter when you write a macro like this, you must remember to add brackets to each parameter when writing the Macro. Otherwise, when someone calls your macro, it will cause a lot of trouble if the expression is used. But even if you do it like this, something strange will happen as follows:

Int A = 5, B = 0;
Max (++ a, B); // The value of A is increased twice.
Max (++ A, B + 10); // The value of A is increased only once.

In this case, what happens inside Max depends on what value it compares!
Fortunately, you don't have to endure such stupid statements any more. You can use common functions to achieve macro efficiency, coupled with predictable behavior and type security. This is an inline function (see article 33 ):

Inline int max (int A, int B) {return A> B? A: B ;}
However, this is not the same as the macro above, because Max of this version can only process the int type. However, the template can easily solve this problem:

Template <class T>
Inline const T & MAX (const T & A, const T & B)
{Return A> B? A: B ;}

This template generates a complete set of functions, each of which can be converted into two objects of the same type for comparison and then return a reference to a large (constant) object. Because you do not know the T type, transferring a reference to the return result can improve the efficiency (see section 22 ).

By the way, when you plan to use a template to write common functions such as Max, first check the standard library (see clause 49) to see if they already exist. For example, the above mentioned Max, you will be pleasantly surprised to find that you can be cool for future generations: Max is part of the C ++ standard library.

With const and inline, you have reduced the need for preprocessing, but you cannot completely ignore it. It is still a long time to discard # include. # ifdef/# ifndef also plays an important role in controlling compilation. Pre-processing cannot retire, but you must plan to give it a long vacation.

The use of # define rather than const in C is a historical reason (compiler support, library support, etc ). Now with const, you should generally use const instead of # define. Another option is enum.

In addition, const is a modifier. It not only supports constant declaration, but also can modify types and functions.

Of course, some macro definitions (as long as some macros with parameters) cannot be replaced by const, # define must be used.

Constants declared using const and enum can be viewed with symbols in the debugger. # The define macros cannot be seen (the pre-processor has processed them all ).

First, the macro will not be eliminated in the header file and Conditional compilation.

Second, macros are more intuitive than other C ++ technologies. However, it depends on your ability. You must ensure the correctness of macros, And the compiler cannot help you. For example, if your class requires a memory allocation policy, you can insert a macro into the class. Otherwise, you need to use templates and multi-inheritance-like Loki, the simplest way to reuse the single-piece mode is macro!

You can use another example to see the differences on business trips:

# Define a B
# Include <iostream>
Using namespace STD;
Main ()
{
Const int B = 1;
Cout <A <Endl;
}

Bytes -----------------------------------------------------------------------------------

# Define a B + B
# Include <iostream>
Using namespace STD;
Main ()
{
Const int B = 1;
Cout <A * A <Endl;
}

----------------------------------------------------------------------------------

# Define a B + B
# Include <iostream>
Using namespace STD;
Main ()
{
Cout <A * A <Endl;
Const int B = 1;
}

----------------------------------------------------------------------------------

# Define a B + B
# Include <iostream>
Using namespace STD;
Int B = 2;
Main ()
{
Cout <A * A <Endl;
Const int B = 1;
Cout <A * A <Endl;
}

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.