C # vs C ++ 2: GC vs RAII

Source: Internet
Author: User

Resource management

In C language, resource management is a complex and error-prone task. Most Complex C systems face problems such as memory leakage and pointer suspension. On the one hand, this is determined by the characteristics of the underlying language; on the other hand, it is also because the C language features are relatively small, it is heavily dependent on programmers for correct resource management, lack of effective support means.

The positioning of C # And C ++ is different. They adopt two different methods in resource management: GC and RAII. GC enables programs to be built on a higher abstraction level, making resource management more convenient and safer. RAII retains the underlying capabilities of C, in addition, the C ++ feature provides a simple and effective resource management method. We know that the most intense criticism of C ++ often comes from the C community. In my opinion, C programmers can not accept virtual functions or templates, but what is the reason for not accepting RAII? It can be said that RAII is a significant improvement with almost no side effects compared with C ++.

Start with GC:

Reference instead of pointer

C # manage managed memory through CLR, and use reference abstraction instead of pointer to indirectly operate managed memory, so that programmers can use resources securely at a higher level. This makes C # lose the ability to directly manage the memory, but in exchange for the following benefits:

1. type security:In C/C ++, you can convert integers or other types of pointers to specific types through type conversion. This means that pointers are non-type safe, the programmer must ensure the validity of the memory space represented by the pointer. C # references can be considered as a type-safe pointer, and the as operator can ensure the type-safe conversion.

2. Memory sorting:To create an object, you need to dynamically allocate consecutive memory space from the heap. Because the memory size of different objects is different, common First Matching and optimal matching heap allocation algorithms will cause memory fragmentation problems in the heap. The existence of fragments makes the actual available memory smaller than the physical memory, so the generation of fragments should be minimized. One direction is to design a better memory allocation algorithm, and the other is to adjust and optimize the memory through periodic memory sorting. In C/C ++, because the pointer represents an absolute address, there is no general memory sorting algorithm. While C # shields the pointer and makes memory sorting possible by referencing the operation object. PS: this does not mean that C/C ++ memory allocation is weaker than C #. C/C ++ programs can design dedicated memory allocation methods for certain types of objects, even assigning objects to a physical address space is not available in C.

Managed and unmanaged Resources

In C #, resources are divided into managed resources and unmanaged resources. When GC recycles useless object resources, it can automatically reclaim managed resources (such as managed memory), but it must be explicitly released in programs for unmanaged resources (such as Socket, file, and database connections.

The collection of managed resources requires GC to identify useless objects and then reclaim their resources. Generally, useless objects refer to objects that are not reachable through the current system root object and call stack object. An important feature of an object leads to the complexity of judgment on useless objects: circular reference between objects! If there is no circular reference, you can use the simple and efficient method of "reference count" to judge useless objects and collect them in real time. It is precisely because of the existence of cyclic references that GC needs to design more complex algorithms. The biggest problem brought by this is the loss of the real-time resource recovery and the change into an uncertain method.

For the release of unmanaged resources, C # provides two methods:

1. Finalizer: The statement looks like a C ++ destructor, but in essence it is quite different. Finalizer is the terminator called before the object is recycled by GC. The original intention is to release the unmanaged resources here. However, due to the uncertainty of the GC runtime, the release of unmanaged resources is usually delayed. In addition, Finalizer may have unexpected side effects. For example, the recycled object has not been referenced by other available objects, but Finalizer has made it available again, this damages the atomicity of the GC garbage collection process and increases the GC overhead.

2. Dispose Pattern: C # provides the using keyword to support Dispose Pattern for resource release. In this way, unmanaged resources can be released in a definite way, and the using structure provides exceptional security. Therefore, we generally recommend that you use Dispose Pattern and check it in Finalizer. If you forget the explicit Dispose object, you can release the resource in Finalizer.

It can be said that GC brings security and convenience to the program, but it also pays a lot of cost: First, it loses the real-time recovery of managed resources, which is fatal in real-time systems and resource-constrained systems; second, managed resources and non-managed resources are not managed in a unified manner, resulting in separate concepts. C ++ is positioned as the underlying development capability, so it is difficult to understand that GC is not a language feature of C ++. Although we can see GC in C ++ 0x and various third-party libraries, GC is not so important for C ++ and is a useful supplement at most. C ++ is strong enough to stand out for C and compete with C # GC in its RAII.

Stack Semantics

Before introducing RAII, let's take a look at a C ++ interview question: "refactor the following code to remove unnecessary try catch when resources are correctly released"

// C ++

Void f (){

Try {

Int * ptr = new int (123 );

... // Do something with ptr

Delete ptr;

}

Catch {

Delete ptr;

}

}

In the Code, the new int allocates memory on the heap and carefully releases the memory through delete. This is a typical C-style C ++ code. Although the advanced syntax such as try and catch is used, the resource management method is still C. The unique method of C ++ can be re-constructed as follows:

// C ++

// Define a resource proxy Template

Template <typename T>

Class Resource {

Public:

Resource (T * ptr) {this-> ptr = ptr;} // initialize Resources in the constructor

~ Resource () {delete ptr;} // release resources in the destructor

T & operator * () {return * ptr;} // reload * operator

T * operator-> () {return ptr;} // reload-> operator

//... The copy constructor and value assignment operator are omitted.

Private:

T * ptr;

};

Void f (){

Resource <int> r (new int (123 ));

// Do something with r

}

In the f function, we create a Resource template class Resource object r on the stack and provide services through r. It's just such a simple package that saves the tedious and error-prone try and catch, No matter what internal issue f has or throws an exception, both ensure that the memory resources managed by r are correctly released. C ++ ensures that, once the lexical scope is left off, the destructor of the object on the stack will be called under any circumstances. This is the so-called "stack semantics ). In fact, STL already has the intelligent pointer class template auto_ptr, which is similar to the preceding Resource class template.

RAII

RAII is short for resource acquisition is initialization ". It is a design concept proposed by Bjarne Stroustrup, father of C ++. Its core is to bind the resource and object lifecycle, create an object to obtain resources, and destroy and release resources. Under the guidance of RAII, C ++ raised the underlying resource management issue to a higher level of object lifecycle management. In the above example, we regard the memory block acquired by new as a resource, and the r object as a resource proxy object. r should be responsible for obtaining and releasing resources. With the support of stack semantics and operator overloading, the RAII of C ++ is concise, secure, and real-time:

1. concise concept: Binds resources (including memory and non-memory resources) to the lifecycle of objects. The resource class designer only needs to use the class definition to handle resource problems, improving the maintainability of the program.

2. type security: The resource proxy object is used to encapsulate resources (pointer variables) and the operator overload is used to provide pointer operations for ease of use, but the type-safe interface is exposed to the outside.

3. Exception Security: Stack semantics ensures the call of object destructor and improves program robustness.

4. Release Timeliness: Compared with GC, RAII achieves the same real-time performance as manual resource release, so it can undertake the important tasks of underlying development.

Maybe you are still surprised when RAII is so simple, the main content about RAII has been introduced. Simplicity does not mean simplicity. In my opinion, RAII is a specific mechanism, although it is not the same as GC, however, my deep understanding of the philosophical relationship between objects and resources makes Bjarne Stroustrup awesome!

Finally, we have to remind you that the concept of RAII is simple, but you still need to be careful when implementing it. For example, for STL auto_ptr, it can be regarded as the resource proxy object, and the assignment between auto_ptr objects is a special note. Simply put, the meaning of the assignment between resource proxy objects does not meet the requirement of "equal assignment", and its meaning is the transfer of resource management right.

What is "Equal Value assignment? For example:

Int;

Int B = 10;

A = B; // after this sentence is executed, a = B

However, this is not true for resource proxy objects, for example:

Auto_ptr <int> a (null );

Auto_ptr <int> B (new int (123 ));

A = B; // after this sentence is executed,! = B. The meaning of the assignment is that B grants the Resource Management Right to.

Summary

The following describes the Resource Management Methods of C # And C ++: GC and RAII.

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.