C ++ programming Specification 2 initialization and type conversion

Source: Internet
Author: User

2 initialization and type conversion

2.1 declaration, definition and initialization

Rule 2.1 prohibits the use of memcpy and memset to initialize non-pod objects

Note: The full name of pod is "plain old data", which is the c ++ 98 standard (ISO/IEC 14882, first edition)

The pod type mainly includes int, Char, float, double, enumeration, void, pointer, and other primitive types.

Types and their collection types, which cannot be encapsulated or subject to object features (such as user-defined constructor/assignment/destructor, base class, and virtual function)

Number ).
Non-pod type, such as non-set Class Object, may have virtual functions, and the memory layout is uncertain, which is related to the compiler.

Copying with memory may cause serious problems.

Even if Direct Memory copying and comparison are used for classes of the set type, Information Hiding and data protection are damaged

Memcpy and memset operations.

Example: The xxx Product Program exits abnormally (core dump ).

After the simulation in the field environment, the program generates coredump because memset (this, 0,

Sizeof (* This) class initialization, the virtual function table pointer of the class is cleared, resulting in the use of a null pointer.

Solution: Use the C ++ constructor to initialize class objects. Do not use the memset function to initialize class objects.

We recommend that you declare and initialize the 2.1 variable when using it.

Note: It is a common low-level programming error that does not assign an initial value to a variable before use. Declare and initialize variables before use, which is very convenient

To avoid such low-level errors.

When all variables are declared at the beginning of the function, the variables are used only later. The scope covers the entire function implementation, which may cause the following problems:

Difficult to understand and maintain programs: the definition and use of variables are separated.

Variable Initialization is difficult: at the beginning of the function, there is often not enough information to initialize the variable.

NULL values (such as zero) are usually a waste of initialization. If a variable is used before it is assigned a valid value, errors may occur.

The principle of minimizing the scope of variables and the principle of nearest statement make the code easier to read and understand the type and initial value of variables.

In particular, the initialization method should be used to replace the Declaration and then assign values.

Example:

// Bad example: separation of declaration and initialization
String name; // not initialized during Declaration: the default constructor is called.
//.......
Name = "zhangsan"; // call the value assignment operator function again. It is difficult to declare and define the function in different places.

// A good example: Declaration and initialization are integrated and easy to understand
String name ("zhangsan"); // call the constructor once.

We recommend that you use the "init" function to avoid complex initialization by constructors.

Note: just as the variables of a function are initialized inside the function, the best initialization place for class data members is the constructor and data.

All Members should be initialized in the constructor whenever possible.

The init () function can be used for initialization in the following cases:

You need to provide the initialization response information.

An exception may be thrown during data member initialization.

Data member initialization failure may cause initialization of this type of object to fail, resulting in uncertainty.

Data member initialization depends on the this pointer: the object is not constructed when the constructor is not completed, and this cannot be used in the constructor.

Member;

Virtual functions must be called for data member initialization. Calling virtual functions in constructor and destructor will lead to undefined behavior.

For example, an exception may be thrown during data member initialization:

Class cpprule
{
Public:
Cpprule (): Size _ (0), res (null) {}; // initialize the value only
Long Init (INT size)
{
// Initialize size _ Based on Input parameters and allocate resources res
}
PRIVATE:
Int size _;
Resourceptr * res;
};
// Usage:
Cpprule;
A. INIT (1, 100 );

We recommend that you initialize the 2.3 initialization list in strict sequence of member declarations.

Note: The Compiler initializes the data according to the sequence declared by the data member in the class definition, instead of in the initialization list,

If you disrupt the initialization list order, it does not actually work, but it will lead to confusion in reading and understanding, especially between member variables.

The dependency may cause bugs.

Example:

// Bad example: the initialization order is inconsistent with the Declaration Order
Class employee
{
Public:
Employee (const char * firstname, const char * lastname)
: Firstname _ (firstname), lastname _ (lastname)
, Email _ (firstname _ + "." + lastname _ + "@ huawei.com "){};
PRIVATE:
String email _, firstname _, lastname _;
};
Class Definition email _ is declared before firstname _ and lastname _. It will be initialized first, but uninitialized

Firstname _ and lastname _ Cause an error.

When declaring members, they should be declared in sequence based on their mutual dependencies.

2.4 specify the initialization sequence of global and static objects with external dependencies.

Note: If the member variables of Global Object A have external dependencies, for example, dependent on another global variable B, access B in the constructor of,

The implicit rule is that B is initialized before a. However, the initialization and destructor sequence of global and static objects are not strictly defined, and B cannot be guaranteed.

Initialization has been completed, and every generation of executable programs may change, which is difficult to locate.

Generally, the singleton mode or the dependency global object is defined in a file to define the initialization sequence.

In the same file, if global object A is defined before global object B, then a will be initialized before B, but all

There is no fixed initialization sequence for the local object. You can initialize a file that is not recycled during running in main () or pthread_once ().

Pointer.

2.2 type conversion

Avoid using the type branch to customize the behavior: The type branch to customize the behavior is prone to errors, is an obvious sign of the attempt to write C code in C ++.

This is a very inflexible technology. When you want to add a new type, the compiler will not tell you if you forget to modify all the branches. Use Template

And virtual functions, let the type rather than calling their code to determine the behavior.
Rule 2.2 uses C ++-style type conversion instead of C-style type conversion

Note: The type conversion of C ++ is more eye-catching and easier to find due to the use of keywords. in programming, programmers are forced to stay thinking for a moment.

Use force conversion with caution.

C ++ uses const_cast, dynamic_cast, static_cast, reinterpret_cast, and other new types for conversion. They allow

User selects the appropriate level of conversion, rather than using a conversion character as C.

Dynamic_cast: Mainly used for downstream conversion. dynamic_cast has the type check function. Dynamic_cast has certain overhead,

We recommend that you use it in the debugging code.

Static_cast: similar to C-style conversion, it can be forced conversion of values, or uplink conversion (converting the pointer or reference of a derived class to the base class

Pointer or reference ). This conversion is often used to eliminate type Ambiguity Caused by multiple inheritance and is relatively secure. Downstream Conversion

When converting a needle or reference to a pointer or reference of a derived class, because there is no dynamic type check, it is not safe and does not advocate downlink conversion.

Reinterpret_cast: used to convert irrelevant types. Reinterpret_cast forces the compiler to weight the memory of an object of a certain type.

It is interpreted as another type, and the relevant code can be transplanted badly. We recommend that you comment on the usage of reinterpret_cast <> to help reduce

Few maintainers are concerned about this conversion.

Const_cast: used to remove the const attribute of an object so that the object can be modified.

Example:

Extern void fun (derivedclass * PD );
Void gun (baseclass * pb)
{
// Bad example: forced conversion of the C style. conversion may result in inconsistent object la s, no compilation error, and crash during runtime.
Derivedclass * Pd = (derivedclass *) Pb;

// Good example: forced conversion of C ++ style, clearly knowing that Pb actually points to derivedclass
Derivedclass * Pd = dynamic_cast <derivedclass *> (PB );

If (PD)
Fun (PD );
}

Recommendation 2.5 avoid reinterpret_cast

Note: reinterpret_cast is used to convert irrelevant types. Try to use reinterpret_cast to forcibly convert one type to another

Type, which compromises the security and reliability of the type and is an insecure conversion. Avoid conversion between different types.

Recommendation 2.6 avoid using const_cast

Note: const_cast is used to remove the const attribute of an object.

The const attribute provides a sense of security, allowing programmers to know that this definition is fixed and does not need to worry about subsequent changes. If

The elimination of const attributes that programmers do not know can cause many serious consequences.

Example: bad examples

Unsigned const int arraysize = 1024;
Int & newarraysize = const_cast <Int &> (arraysize );
Newarraysize = 2048;
If arraysize is not accessed through reference or pointer, the value of arraysize is always 1024. However

If the pointer or reference is passed to another function for a value, the value is changed to 2048.

Example: A bad example: Force remove the const attribute of the input parameter, so that the function can modify the input parameter.
Void setobj (tbase const * OBJ)
{
// M_pobj is defined:
Tbase * m_pobj;
M_pobj = const_cast <tbase *> (OBJ );
M_pobj-> value = 123;
}

It is recommended that 2.7 replace dynamic_cast with a virtual function

Note: Many programmers who have just switched from the C language are used to this idea: if the object type is T1, perform some processing. If the object type is T1

If the type is T2, perform additional processing. However, C ++ provides a better solution: virtual functions.

Compared with the dynamic_cast type conversion, virtual functions:

Virtual functions are more secure and there will be no forced conversion error;

Higher efficiency of virtual functions: use function pointers to avoid conditional judgment;

The virtual function does not need to determine the actual object type during encoding, while dynamic_cast must inform you of the type to be converted to. If

If the type is incorrect, a null pointer is returned or an exception is thrown;

Stronger applicability of virtual functions: virtual functions are actually dynamically bound; type conversion when a derived class is added or deleted, dynamic_cast

The corresponding code must be added or removed.

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.