Title you need to pay attention to 11 points for C chinahai (translation)
Keyword C , pointer, class, grammar, library
Source http://www.codeproject.com/
The following points are to apply for all C programmers. I said that they are the most important
It is because these points mentioned in these points are usually could not be found on the C book or on the website. Such as: pointing
Members' pointers, this is where many materials are not willing to mention, and it is also a place where it is wrong, even
Some advanced C programmers are also true.
The main points here are not only to explain how to write better code, but more is to show the language rules.
s things. Obviously, they are permanent in C programmers. I believe this article will make
You are not harvest.
First, I will return some questions from different levels of C programmers. I am surprised
There are many experienced programmers, they have not realized. Hyers should also appear in standard header files.
in.
Key 1:
Many C programmers are still using
What is the difference between these? First of all, we started against the head of the. H symbols to continue with the standard head
Document. Continue to use outdated rules are not a good way. From a functional perspective,
flow. In addition, the C standard specification interface of the input and output flow has been improved in some subtle details, so
Chengdu is declared in STL, but the compositions of
Because these substantially different, you cannot confuse these two libraries in a program. A kind of habits
It is used to usually use
Inheritance can be used to continue with the consistency of the old holding code.
Point 2: Places that should be noted when using reference to pass parameters
When passing parameters with reference, it is best to declare the reference to a const type. The advantage of this is: telling
The program cannot modify this parameter. In this example, the function f () is a reference to pass:
Void F (Const Int & I);
int main ()
{
f (2); / * ok * /
}
This program passes a parameter 2 to f (). At runtime, C creates a value of 2 Int type
Time variables and deliver it to f (). This temporary variable and its reference from f () called start to be created.
And exist until the function returns. When you return it, you will be removed immediately. Note that if we don't quote
Const qualifiers, the function f () may change the value of its parameters, which is more likely to make the program unsenerated.
behavior. So don't forget const.
This point is also applicable to user-defined objects. You can add a reference to the temporary object if it is
CONST type:
Struct a {};
Void F (Const A & A);
int main ()
{
f (a ()); // OK, passed a constant reference for temporary A
}
Point 3: "Common Isolation" expression form "comma separation" expression is inherited from C, in the for- and while-cycles. Of course, this
The rules of grammar are considered not intuitive. First, let's take a look at what is "comma separation" expression form.
An expression consists of one or more other expressions, separated by a comma, such as:
IF ( x, --y, cin.good ()) // three expressions
This IF condition contains three expressions separated by commas. C will calculate each expression but complete
The result of the "comma separation" expression is the value of the rightmost expression. Therefore, only when cin.good () returns
When True, the value of the IF condition is TRUE. Here is another example:
INT j = 10;
INT i = 0;
While ( i, --j)
{
/ / Until J = 0, the loop ends, when cycles, I is constantly playing
}
Point 4, use the constructor of the global object to call the function before the program starts
Some applications need to call other functions before starting the main program. Such as: transmissions process function, registration
Functional functions must be called before the actual program is run. The easiest way is to pass a global object
The constructor calls these functions. Because global objects are constructed before the main program begins, these functions
Will return results before main (). Such as:
Class Logger
{
PUBLIC:
Logger ()
{
Activate_log (); // Translator Note: Call the function that you need to run first in the constructor
}
}
Logger log; // A global instance
int main ()
{
Record * PREC = Read_Log (); // Translator Note: Read log file data
//.. code
}
The global object log is constructed before the main () runs, and the log calls the function activate_log (). From
However, when Main () begins to execute, it can read data from the log file.
There is no doubt that memory management in C programming is the most complicated and easier to show bugs. Direct access
Ask the original memory, dynamic allocation storage, and maximize the efficiency of C instructions, make you try to avoid
BUG of memory.
Point 5: Avoid pointers with a pointing function using complex constructors
The pointer to the function is one of the worstable syntax of C . Can you tell me what the following statement?
?
Void (* p [10]) (void (*));
P is a "pointing by 10 pointers to a returning Void type and pointing to another without returning and no
The array of functions "." This troublesome syntax is really difficult to identify, isn't it? You can actually
Single uses TypeDef to declare the functionality of the above statement. First, use the typedef declaration "point to one
Pointer with no return and uncontrolled function:
Typedef void (* pfv) ();
Then, the declaration "another function pointer to the non-return and use PFV":
Typedef void (* pf_taking_pfv) (PFV);
Now, a array composed of 10 tops of the top:
PF_TAKING_PFV P [10];
With Void (* p [10]) (void (*)) to achieve the same effect. But this is not more readable.
!
Key 6: Pointing to the member
A class has two basic members: functions members and data members. Similarly, pointers pointing to members
There are two: points to the pointer of the function member and pointer to the data member. After that, it is not common because the class
Generally, there is no public data member, which is used only when the coordination structure and class (Class) are used when inheriting CLOS.
Pointing to a member's pointer is one of the most difficult constructs in the C syntax, but this is also a C strongest
Large characteristics. It allows you to call a class of function members without having to know the name of this function. this one
Very agile calling tool. Similarly, you can also check and change by using a pointer to the data member.
Change this data without knowing its member name.
Pointer to point to data
Despite the beginning of the beginning, the grammar of the pointer to the member will make you a little confused, but you will send it.
It is now actually similar to ordinary pointers, but it is only the * number :: Symbol and class name, example:
Define a pointer to the INT type:
INT * PI;
Define a data member to the INT type class:
INT A :: * PMI; // PMI is a member pointing to a INT type of class a
You can initialize it like this:
Class A
{
PUBLIC:
Int Num;
INT X;
}
INT A :: * PMI = & a :: Num;
The above code is a statement that pointing a INT type of class A and initials it to this NUM
Members' address. By adding * you can use and change the value of the Num member of class A:
A A1, A2;
INT n = a1. * PMI; // assigns A1.NUM to N
A1. * PMI = 5; // Assign 5 assigned to A1.NUM
A2. * PMI = 6; // Assign 6 assignments to 6A2.NUM
If you define a pointer to class A, then the above operation you must use -> * Operation
for:
A * pa = new a;
INT N = Pa -> * PMI;
PA -> * PMI = 5;
Pointer to function member
It consists of the data type returned by the function member, and the class name is followed by :: symbol, pointer name, and function
Number list. For example: a pointer to a function member of class A (this function returns an int type):
Class A
{
PUBLIC:
INT func ();
}
INT (a :: * pmf) ();
The above definition is to say that PMF is a pointer to function member func () of class A. In fact, this
There is no difference between a pointer and a generic pointing function, just it contains the name of the class and: characters
number. You can call this function in any part of any * PMF.
Func ():
PMF = & a :: func;
A a a;
(a. * pmf) (); // call A.Func ()
If you define a pointer to the object, then the above operation is used to use -> * instead:
A * PA = & A;
(Pa -> * pmf) (); // call PA-> FUNC ()
Pointer to point to function members should consider polymorphism. So when you call a virtual function member through the pointer
This call will be reclaimed dynamically. Another place to pay attention to, you can't take a configuration letter
The address of the number and destructor.
Point 7 to avoid memory fragmentation
There will often be such a situation: Your application is generated every time you run once due to the defects of the program.
Memory vulnerability leaks memory, and you repeat your program in the period, you can imagine that it will also
Crash the system. But how can I prevent it? First, try less dynamic memory. In most cases
Under, you may use static or automatic storage or STL containers. Second, try to distribute large blocks of memory without
It is only a small amount of memory. For example: allocate the memory required by an array instance, not one
Only the memory of an array element is allocated.
Total 8, is DELETE or delete []
There is an absurd statement in the programmer: use Delete instead of delete [] to delete an array type!
For example:
INT * p = new int [10];
Delete p; // error, it should be: delete [] P
The above program is completely wrong. In fact, use Delete on a platform instead of delete []
Applications may not cause the system to crash, but that is purely luck. You can't guarantee that your app is not
It is compiled on another compiler, run on another platform, so please use Delete [].
Point 9, optimize members' arrangement
The size of a class can be changed below:
Struct a
{
BOOL A;
INT B;
BOOL C;
}; // sizeof (a) == 12
SIZEOF (a) on my computer is equal to 12. This result may surprise you because a member of the member
The number is 6 bytes: 1 4 1 byte. Where is the other 6 bytes? Compiler behind each BOOL member
Both plug-in bytes to ensure that each member is arranged in 4 bytes in order to be boundary. You can reduce A
Size, by the following ways:
Struct B
{
BOOL A;
BOOL C;
INT B;
}; // sizeof (b) == 8
This time, the compiler only inserted 2 bytes after the member C. Because B accounts for 4 bytes, it is very self
However, it is arranged as a word in the form of a word, and the size of A and C 1 1 = 2, plus 2 bytes, just press two
Arrange B in the form of a word.
Total 10, why inherited a class without a false argument function is dangerous?
A class without a false aromacy means that it cannot be used as a base class. Such as std :: string,
Std :: Complex, and Std :: Vector are like this. Why inherit a function of a fault
Is the class dangerous? When you have a public inherit, you point to the refer to the new class object when you create a related class inherited from the base class.
Needle and references actually point to the origin of objects. Because the destructor is not a virtual function, so when you delete
When such a class, C will not call the destructor chain. For example, explain:
Class A
{
PUBLIC:
~ A () // is not a virtual function
{
// ...
}
}
Class B: public a // fault; A no false prefix function
{
PUBLIC:
~ B ()
{
// ...
}
}
int main ()
{
A * p = new b; // looks right
Delete p; // fault, the sector of B is not called
}
Point 11, category nested by friends class
When you declare a nested class with a friend class, put the friend declaration behind the nested category declaration, not
front.
Class A
{
Private:
INT I;
PUBLIC:
Class B // Nested Category Before
{
PUBLIC:
B (A & a) {a.i = 0;
}
Friend class b; // friend class statement
}
If you put the friend class statement in front of the declaration nested class, the compiler will abandon the other sounds after the friend class.
Bright.
From 9cbs