Clause 8: rules for the use of smart pointers familiar with more terms please go to the original article: http://blog.csdn.net/liuchang5
In chapter 1, we came into contact with the general interface reference counting rules (Clause 2 ). Before starting this chapter, let's take a look at the rules that smart pointers should follow. The rules used by smart pointers are more complex than those used by interface pointers, but take into account the convenience and security provided by smart pointers. It may be worth remembering these rules:
1. Immediately bind a resource to a smart pointer (raiI) upon application ). For details, see Clause 1.
2. Before the function returns an interface pointer, call dettach () to promptly unbind the smart pointer from the interface pointer. For details, see clause 12.
3. The intelligent pointer must use the attach () function to receive the interface pointer from the return value of a function. For details, see clause 12.
4. When the outgoing interface pointer is used, make sure that the passed smart pointer is null. For details, see section 25.
Clause 9: Try not to place smart pointers on the heap
Let's take a look at the Code:
void SomeApp(){ CComPtr<ICalculator>* pspMyCalculator = new CComPtr<ICalculator>; (*pspMyCalculator).CoCreateInstance(CLSID_CALCULATOR); pspMyCalculator->DoSomething(); delete pspMyCalculator;}
I promise that you won't write the code like above, because he has extracted the title of "intelligence" from the smart pointer. Of course, the addref will still be called in the overload of the value assignment operator, and the smart pointer still provides the type security feature. However, it is extremely secure. The reference count is released automatically, which is far away from us. Think about what happens when dosomething () throws an exception? Resource leakage ......
Maybe you say that you will never be stupid enough to write the above Code. Then, similar tragedies still happen, but it is even more concealed:
class MyClass{public: MyClass(); ~MyClass(); DoSomething();private: CComPtr<ICalculator> m_spCalculator;};
This statement is correct, but the following usage poses a potential problem.
Void someapp () {myclass * pmyclass = new myclass (); // OH ~ There is still a problem .... Delete pmyclass ;}
Imagine what would happen in the above Code, and the situation is not optimistic. The condition for the smart pointer to exit the stack is delete pmyclass. But what if he can never execute it? Memory leakage occurs again.
You may say that this problem is too obvious, but my example only shows you where it is. In the real code, myclass may be a member attribute of another object on the stack, and the application process of this object on the stack may be in the init () function, but the release process is in the uninit () function () in the function, the difference is 108,000. Discover how difficult he is.
Therefore, the advice is "do not place smart pointers on the heap as much as possible", so you must be careful with the appearance of smart pointers on the heap. But you may have the last question: why is it "as much as possible" instead of "not "? Do we still need to stack smart pointers in some cases?
The answer is yes. We need smart pointers on the stack. You may ask, what should we do if we really need a resource on the stack?
A special case is that the resource life cycle is the same as that of the program process, so there is no difficulty in releasing resources in advance. It is safe:
Class theapp {public: theapp ();~ Theapp (); dosomething (); Private: ccomptr <idocument> m_spdocument; // This interface is used throughout the life cycle of the program}; theapp g_theapp; // Global Objects will open up space on the stack. Theapp * g_ptheapp = NULL; // or in this way, it is new in another place.
If the life cycle is global, placing it on the stack will not cause too many problems. After all, he may need to release it after the program ends. But what if his life cycle is not global and he needs to apply dynamically?
The correct method is to use a resource management object or smart pointer object to take charge of the resources on the stack. He will probably look like this:
Class theapp // If theapp needs to be applied to the nearest stack {public: theapp ();~ Theapp (); dosomething (); Private: ccomptr <idocument> m_spdocument; // a smart pointer that will appear in the heap}; auto_ptr <theapp> func () {auto_ptr <theapp> sptheapp (New theapp); // use another smart pointer to stack resources. ... Return sptheapp; // pass it out to continue the lifecycle of the object on the stack}
Remember to "Try not to place smart pointers on the heap ". OK, it's over ~