C ++ built-in type selection and usage summary

Source: Internet
Author: User
Tags classe constructor

Precautions for selecting and using C ++ built-in types


(1) type selection

① When it is clear that the value cannot be negative, the unsigned type is used.

② For an integer, either int or long. Short is generally too small. Of course, if it is clear that the data does not exceed two bytes, it can be used, while long is long in many compilers and int. Long is a new type of C ++ 11, which is an 8-byte int.

③ Use signed char or unsigned char whenever possible, instead of char. Because char is unsigned in some compilers, it is signed in some compilers.

④ Double is used for floating point operations. The computing cost of float and double is almost the same (or even the double is faster than float on some machines, Primer said), but it is clear that the double precision is high, and longdouble is generally not necessary.

Note: The above is only a general suggestion. It is not a standard, that is, it is only recommended to do so, rather than a mandatory requirement.

(2) notes:

① Do not use the bool value for calculation. The following code

Bool B =-10;
Int a = 10;
Cout <a + B <endl;

Expected result 11 is displayed.

The bool value is only 0 and 1 (true and false). If a non-0 value is assigned to bool, the compiler treats the bool value as 1. If 0 is assigned to bool, the compiler treats the bool value as 0.

Note: In fact, this situation will hardly happen in real programming. Here we just want to talk about the processing method of the compiler when the non-bool value is assigned to the bool value.

② Avoid using the unsigned number and number in the same expression at the same time. The following code

Unsigned int a = 10;
Int B =-42;
Cout <a + B <endl;

Result 4294967264 is displayed.

The reason is that when the number of signed symbols and the number of unsigned symbols are calculated together, the number of signed symbols is considered as the number of unsigned symbols. The above int B =-42 is represented by a complement in the machine, and its binary complement is regarded as the number of unsigned, that is, 232-42 = 4294967276-42 = 4294967254, plus the value of a 10, is 4294967264.

③ Do not use the unsigned number as a loop control variable. The following code


For (unsigned I = 5; I> = 0; -- I) // here unsigned I is interpreted by the compiler as unsigned int I by default
    {
Cout <I <"";
If (4294967291 = I)
        {
Cout <endl;
Break;
        }
    }



The following result is displayed.


The reason is the same as above. When I is reduced to-1, the compiler considers it to be 232-1 = 4294967295, so the loop continues. Obviously, if we do not intentionally add the break statement to exit the loop when I =-5 (that is, the 4294967291 that the compiler considers), the program will fall into an endless loop. However, if we don't know that this is an unsigned task, we will feel inexplicable, incredible, and puzzled until we get mad.

Some people may say that it is okay to change the for loop to for (unsigned I = 6; I> 0; -- I? Or someone will say: who is free to use the unsigned type as a loop control variable? Yes, it does, but it does not mean that we can always avoid the above errors, especially when we accidentally "implicitly" use the unsigned type as a loop control variable. (For example, we may calculate a value from an unsigned integer elsewhere in the program, and then use this value as a loop control variable in for or while)

Therefore, we recommend that you always keep in mind that you should never use the unsigned type for loop control variables unless necessary.


C ++ built-in type and class type initialization

# Include <iostream>
# Include <vector>
# Include <string>
Using namespace std;

Int global_n; // The built-in type variable of the function in vitro is automatically initialized to 0

//////////////////////////////////////// //////////////////////////////////
// The system will provide a default constructor to construct the ClassA object.
Class ClassA
{
Public:
Void output () {cout <"ClassA" <endl ;}
};

//////////////////////////////////////// //////////////////////////////////
// The default constructor does not initialize the data member m_Value. This will make the member undefined !!
// The constructor with an int parameter does not provide the default constructor. The ClassB object cannot be constructed by default !!
Class ClassB
{
Public:
ClassB (int v) {m_Value = v ;}
Void output () {cout <"ClassB, Value:" <m_Value <endl ;}
Private:
Int m_Value;
};

//////////////////////////////////////// //////////////////////////////////
// Class containing data members of the ClassB type, because ClassB does not have a default constructor,
// The ClassUseB object cannot be constructed by default !!
Class ClassUseB
{
Public:
Void output () {cout <"In ClassUseB-"; m_Value.output ();}
Private:
ClassB m_Value;
};

//////////////////////////////////////// //////////////////////////////////
// ClassC provides the default constructor and uses the initialization list to correctly initialize data members.
Class ClassC
{
Public:
ClassC (): m_Value (0 ){}
Void output () {cout <"ClassC, Value:" <m_Value <endl ;}
Private:
Int m_Value;
};

// Because ClassC has a default constructor, classes that use ClassC as data members can be constructed by default.
Class ClassUseC
{
Public:
Void output () {cout <"In ClassUseC-"; m_Value.output ();}
Private:
ClassC m_Value;
};

//////////////////////////////////////// //////////////////////////////////
// Use the constructor initialization list to Initialize two data members. Note that the order and definition order are inconsistent.
Class ClassD
{
Public:
ClassD (): m_ B (2), m_A (1 ){}
Void output () {cout <"ClassD, Value:" <m_A <"," <m_ B <endl ;}
Private:
Int m_A;
Int m_ B;
};

//////////////////////////////////////// //////////////////////////////////
// In the initialization list, m_A initializes itself based on the m_ B value, which leads to errors or undefined behaviors,
// The initialization sequence should be consistent with the sequence defined by the data member.
Class ClassE
{
Public:
ClassE (): m_ B (1), m_A (m_ B * 2) {}// m_A will initialization fail! Its value is unknown.
// ClassE (): m_A (m_ B * 2), m_ B (1) {}// same as above
// ClassE (): m_A (1), m_ B (m_A * 2) {}// the class 2 is initialized successfully.
Void output () {cout <"ClassE, Value:" <m_A <"," <m_ B <endl ;}
Private:
Int m_A;
Int m_ B;
};

//////////////////////////////////////// //////////////////////////////////
// Members of the const type or reference type, and members of the class type without the default constructor,
// Initialization must be performed in the constructor initialization list
Class ClassF
{
Public:
// Failed
// ClassF ()
//{
// M_Const = 1;
// M_Ref = 2;
// M_ B (3 );
//}
ClassF (): m_Const (1), m_temp (2), m_Ref (m_temp), m_ B (3 ){}
Void output ()
    {
Cout <"ClassF, m_Const:" <m_Const
<", M_Ref:" <m_Ref <",";
M_ B .output ();
    }
    
Private:
Const int m_Const;
Int m_temp; // provides variable reference for m_Ref
Int & m_Ref;
ClassB m_ B;
};

//////////////////////////////////////// //////////////////////////////////
// Use the default real-name constructor
Class ClassG
{
Public:
ClassG (int v = 1): m_Value (v ){}
Void output () {cout <"ClassG, Value:" <m_Value <endl ;}
Private:
Int m_Value;
};

//////////////////////////////////////// //////////////////////////////////
// Implicit conversions
// The constructor that can be called with a single real parameter defines an implicit conversion from the form parameter type to the class type
Class ClassH
{
Public:
ClassH (): m_Str ("null"), m_Int (0 ){}
ClassH (string & s): m_Str (s), m_Int (1 ){}
ClassH (int I): m_Str ("null"), m_Int (I ){}
Void output () {cout <"ClassH, m_Str:" <m_Str <", m_Int:" <m_Int <endl ;}
Private:
String m_Str;
Int m_Int;
};

//////////////////////////////////////// //////////////////////////////////
// Use explict to suppress implicit conversions
// To perform type conversion, you must explicitly call the corresponding constructor.
Class ClassI
{
Public:
ClassI (): m_Str ("null"), m_Int (0 ){}
Explicit ClassI (string & s): m_Str (s), m_Int (1 ){}
Explicit ClassI (int I): m_Str ("null"), m_Int (I ){}
Void output () {cout <"ClassI, m_Str:" <m_Str <", m_Int:" <m_Int <endl ;}
Private:
String m_Str;
Int m_Int;
};





Int main ()
{
// The built-in type variables in the function body are not automatically initialized, and the copy initialization
Int n1 = 10;
// The built-in type variables in the function body are not automatically initialized and directly initialized.
Int n2 (10 );
// N3 is not initialized. Using n3 will lead to undefined behavior.
// VC ++ 2005: Run-Time Check Failure #3-The variable 'n3 'is being used without being defined.
Int n3;
// Use the explicit constructor call syntax without parameters. The built-in type variables are initialized to 0.
Int n4 = int ();

Cout <"global_n:" <global_n <", n1 :"
<N1 <", n2:" <n2 // <", n3:" <n3 <
<", N4:" <n4 <endl;
Cout <endl;

ClassA;
A. output ();
Cout <endl;

// The following operations will fail, because ClassB does not have the default constructor!
// ClassB B;
// B. output ();
// ClassUseB ub;
// Ub. output ();
// ClassB arrB [3];
// ArrB [0]. output ();
// Vector <ClassB> vecB;
// VecB. push_back (B );
// VecB [0]. output ();
// The ClassB object must be constructed using the constructor.
ClassB b2 (2 );
B2.output ();
Cout <endl;

// The following structure is correct, because ClassC can be constructed by default
ClassC c;
C. output ();
ClassUseC uc;
Uc. output ();
ClassC arrC [3];
ArrC [0]. output ();
Vector <ClassC> vecC;
VecC. push_back (c );
VecC [0]. output ();
Cout <endl;

// ClassD, ClassE, and ClassF demonstrate the usage and precautions of the constructor initialization list
ClassD d;
D. output ();
ClassE e;
E. output ();
ClassF f;
F. output ();
Cout <endl;

// Use the default real-name constructor
ClassG g;
G. output ();
Cout <endl;

// Implicit class type conversion
ClassH h1;
String str = "test ";
ClassH h2 = str;
ClassH h3 = 3;
H1.output ();
H2.output ();
H3.output ();
Cout <endl;

// Use the explicit keyword to limit the implicit conversion of constructors
ClassI i1;
// ClassI i2 = str; // ERROR, implicit conversion is restricted
// ClassI i3 = 3; // ERROR, implicit conversion is restricted
ClassI i4 (str); // OK, explicit conversion
ClassI i5 (3); // OK, explicit conversion
I1.output ();
I4.output ();
I5.output ();
Cout <endl;

Cout <endl;
System ("PAUSE ");
}

Related Article

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.