PREFER C
Written by Li Zhiyong
Foreword
After reading "Eric Raymond's evaluation of several major development languages", it feels that it is extremely biased against C . C itself supports multi-style design, that is, you can use only OO, GP, and only use structured methods to perform programming. The efficiency is basically consistent compared to C. And you can enjoy the benefits of more stringent type system checks, inline functions, namespace, and operators. If you sacrifice a little efficiency, you can also use an exception handling.
I used to write an article for the project team members, calling for everyone from C . I am now posted this article, and I am looking at home ax.
1, more stringent type system than C
Char szbuf [MAX_PATH];
Word J = SZBUF;
It is permitted in C which is a warning, and it is illegal in C .
Word Add (Word A, Word B);
Add (1, SZBUF); may result in catastrophic consequences.
More critical is to process the callback function:
For example: API Function Prototype Int SetabortProc (HDC HDC, AbortProc LPabortproc);
There is setAbortProc (HDCPRN, ABORTPROC) during call;
If AbortProc does not match the AbortProc type, the automatic conversion type will be automatically converted. It is absolutely possible to lead to catastrophic consequences. What is the stack?
In short, C is better in preventing mistakes caused by mistakes, but it is absolutely not forbidden to deliberately break the behavior of type systems. Because it is necessary to be compatible with C, C is not good, the warning is still to do type conversion. Look below:
INT A = 0;
Unsigned b = 0;
INT I;
For (i = 10; i> = b; --i)
{
A ;
}
In fact, this is a dead cycle. The problem is not matched in the I and B types (this is a warning when compiling, not an error). When a comparison must be compared, it will be converted to unsigned, so i> = b will always be true.
2, intelligent resource management
Using C constructors and destructive functions can establish a very complete resource management mechanism to prevent resource leaks as much as possible. Look at the following block:
Void func1 ()
{
Char * szbuf = malloc (50); // Using the VOID * to other types of pointers in c, automatic conversion
------------
Free (SZBUF);
Return;
}
This must have this form of code if it is necessary to return anywhere in allocation and release of memory.
IF (---)
{free (szbuf); return 0;}
Once I forgot to release the memory and return, the memory leak will be generated.
Examples of the C class have such a feature. At the beginning of its scope, the constructor is called, which is called before the scope. The most famous example of using this rule to manage resources is the smart pointer in the standard library (see: More EffevTive C , The C Standard Library and The C Programming Language.
The following is a brief explanation:
Class A;
Void func2 ()
{
A a a; // Constructor is called
--------
Return; // Destructure function is called
}
If the relevant resource allocation is completed in the constructor of CLASS A, how to release the memory in the destructor?
There is no need to worry about the problem with the release of the problem.
A roughly there is a form:
Typedef struct tagpoint {
INT X;
Int Y;
Point, PPOINT;
Class A
{
PPPoint Pointer;
SmartPointer (PPPOINT P)
{
Pointer = P;
}
~ Smartpointer ()
{
IF (Pointer)
DELETE POINTER;
}
Point & Operator * () const
{
Return * Pointer;
}
Point * Operator -> () const
{
Return Pointer;
}
}
This can be like this to use Point:
A Pointer (new point); / / to allocate memory for the POINT structure
Pointer-> x = 5; // Access related elements
/ / The memory allocated for the POINT is automatically deleted when the scope is exceeded.
And every structure writes a class is not cost-effective, so people invented templates. When A application template is defined as this:
Template
{
SmartPointer (T * P)
{
Pointer = P;
}
~ Smartpointer ()
{
IF (Pointer)
DELETE POINTER;
}
T & Operator * () const
{
Return * Pointer;
}
T * Operator -> () const
{
Return Pointer;
}
Private:
T * Pointer;
}
This can be used in this way.
This is like this:
A
Pointer-> x = 5;
/ / The memory allocated for the POINT is automatically deleted when the scope is exceeded.
N many people explained this point of view, but I think the most useful use under Windows is an attachment 1.
Intelligent management of various handles under Windows can be realized.
Author: Jeffey Richter magazine in 2000 fourth msdn, win32 Q & A column
Reading this example requires a point of template and symbol overload.
It is very simple to use:
For example, for the file handle, there is:
CensureCloseHandle Hhandle = CreateFile (-);
Writefile (HHANDLE);
------------
Don't call CloseHandle, it will be automatically called automatically over the scope.
The most exciting application is a smart pointer with reference to the count.
See Annex 2. (Come from the C Standard Library)
3, powerful inline (C does not support this!)
The first time I didn't remember the Link-Time Code Generation (Matt Pietrek MSDN Magazine 2002 5), and I remember that the functionality that the function can be used by the linker can do inline to significantly improve performance. Later, I tried it in VC , the result is really terrible, first talk about how much performance can increase, look at the following procedure, and guess the time spent on the inline function:
Int Add (Int A, INT B)
{
RETURN A B;
}
Inline Int Addinline (Int A, INT B)
{
RETURN A B;
}
All are called in this form:
INT B;
For (int J = 0; J <50000; J )
{
B = add (60, 70);
Assuming the time spenting add () is: 88964NS (under the VC 6.0 Release version), how much is the time spenting addINline?
The true result is 0, that is, the addinline function does not exist at all. After being optimized, the remaining is just a value of 0x82. Of course, this is an extreme example, but from another perspective to make the appropriate function into the inline, it is actually an opportunity to make a greater optimization of the compiler.
Another advantage of Inline.
Everyone knows that the function calls to handle the stack (very few registers). This is part of the inrest of the stack and out of the stack, this part of the code is not in Inline.
For (int J = 0; J <50000; J )
{
B = add (j, j 1);
}
versus
For (int P = 0; P <50000; P )
{
B = addinline (p, p 1);
}
COUT << b; // must use B
The time spent at this point is:
1.10619e 006ns and 331754ns