Gotw # 25 auto_ptr
Difficult: 8/10
problem
Consider the following code: those are good, those are safe, those are legal, those are illegal?
Auto_PTR
Void Sink (auto_ptr
Void f () {
Auto_PTR
SINK (Source ());
SINK (Auto_Ptr
Vector
v.push_back (new t (3));
v.push_back (new t (4));
v.push_back (new t (1));
v.push_back (a);
V.PUSH_BACK (New T (2));
Sort (v.begin (), v.end ());
Cout << A-> Value ();
}
Class c {
Public: /*...*/
protected: /*...*/
Private:
Auto_PTR
}
answer
Consider the following code: those are good, those are safe, those are legal, those are illegal?
Standard Update: This week, this week, the week released, at the WG21 / J16 in the meeting, the final draft of the C language vote. We look forward to whether it can pass and become an ISO formal standard at the next meeting (Nice, March 1998).
At Jersey's meeting, Auto_Ptr is refined to meet the requirements of the Committee. This issue of the special issue reviews the final version of Auto_PTR to find out how and why being modified safer and easy to use, and how to use it better.
summary:
1. All legal use work for Auto_PTR is the same as before, except that you can't use (inevitable to use) empty auto_ptr.
2. Abuse of the danger of Auto_PTR is illegal.
Thanks: Thank Bill Gibbons, Greg Colvin, Steve Rumsby and other carefully modified auto_ptrists. In particular, Greg has been engaged in Auto_PTR and related modifications to meet all aspects of opinions and requirements, and should be praised by the public.
background
Auto_PTR's initial motivation is to make the following code safer:
Void f () {
T * Pt (New T);
/ 9More Code ... * /
delete pt;
}
If f () does not perform the DELETE statement (because premature returnes or abnormalities inside the function body), dynamically assigned objects will not be leaked by DELETE, a typical memory.
One simple way to make it securely encompass this pointer with a "dexter" class pointer object and automatically delete this pointer when it is destructured:
Void f () {
Auto_PTR
/ 9More Code ... * /
} // Cool: PT's DTOR IS CALLED AS It Goes Out of
// scope, and the allocated object is deleted
Now, this code will no longer leak T object, whether it is the function of the function or because of exception, because the destructive function of the PT is always called during the decorment process. Similarly, Auto_PTR can be used to securely enclose pointers. Note: An important detail about security is not mentioned in this item, it is seen in GotW # 62 and "Exceptional C "〗: // File C.h
Class c {
PUBLIC:
C ();
/*...
Private:
Auto_PTR
}
// file c.cpp
C :: c (): PIMPL_ (NEW CIMPL) {}
Now, the destructor no longer needs to delete the PIMPL_ pointer because Auto_PTR will automatically process it. We will discuss this example again at the end.
Source and handover
This is its starting point, but it is better. Based on GREG COLVIN's work and experience, it is very useful if the copy function of Auto_PTR is defined, it is useful to pass (as parameters or return values).
This is the actual mode of operation of the AUTO_PTR in the second manuscript (DEC 1996), and the copy behavior of Auto_Ptr will hand over the target from the source to the target. After copying, only the target auto_ptr "Has" this pointer and deletes it when appropriate, and the source auto_ptr still contains the same object but does not "with" it does not delete it (otherwise there will be twice delete problems). You can still use this pointer to simultaneously owns it or does not have its ATUO_PTR object.
E.g:
Void f () {
Auto_PTR
Auto_PTR
PT2 = Pt1; // Now Pt2 Owns the Pointer, AND
// pt1 does not
Pt1-> dosomething (); // ok (Before last week)
PT2-> dosomething (); // ok
} // as we go out of scope, pt2's dtor deletes the
// Pointer, But Pt1's Does Nothing
Let us see the first part of the code: (Note 1)
Auto_PTR
Void Sink (auto_ptr
in conclusion
| Before NJ After NJ
Legal? YES YES YES
| SAFE? YES YES YES YES
This is the attention of people in Taligents:
l Source () Assign a new object and returns it to the caller with a fully secure method, allowing the caller to get the ownership of the pointer. Even if the caller ignores the return value (of course, you never write the code, right?), The assigned object is still safely deleted.
See GOTW # 21, which proves why this is an important habitual usage, because it returns a function of a strong abnormal security method because it passes through Auto_PTR.
l Sink () Accept a value passed Auto_PTR and take over its ownership. When the Sink () ends, the delete action is executed (assuming SINK () does not pass the ownership to others). Because the SINK () function does not do anything in the function body, call "SINK (a);" equivalent to "A.Release ();".
The following code shows Source () and SINK () behavior: void f () {
Auto_PTR
in conclusion
| Before NJ After NJ
Legal? YES YES YES
| SAFE? YES YES YES YES
Here, f () takes over the ownership of the pointer returned from Source () and (ignoring some of the issues of the F () code rear portion of the F () code automatically deletes it when the automatic variable A is over. This is good, and the value transfer of Auto_PTR is working.
SINK (Source ());
in conclusion
| Before NJ After NJ
Legal? YES YES YES
| SAFE? YES YES YES YES
Since Source () and sink () definition is too simple (for example, empty), this is just a shaped "delete new t (1);". So, is it really useful? Ok, suppose Source is a non-empty factory function and sink () is a non-empty consumption function, then, it has a big meaning and suddenly regularly appear in the real-world program.
SINK (Auto_Ptr
in conclusion
| Before NJ After NJ
Legal? YES YES YES
| SAFE? YES YES YES YES
Once again, a deformed "Delete New T (1)", and when Sink () is a non-empty consumption function and takes over the ownership of the object, it is a useful habitual usage.
Can't do something, and why can't you do
"So," You said, "This is great, it is a good thing to express the auto_ptr's copy is a good thing." Yes, but it also makes you fall into the heat in the water in the least expectation, this is why the draft of the draft 2 The reason for the form of auto_ptr. There is a fundamental question here, I highlight it with the black body:
For Auto_PTR, the copy is not right.
It pointed out the important impact when using Auto_PTR in the model: It must be understood that the copy is unequal. E.g:
Vector
in conclusion
| Before NJ After NJ
Legal? Yes NO
| SAFE? NO NO
This is the first question and is one of the things that the Commission wants to correct. In short, even if the compiler does not even prompt Warning, it is not safe to put auto_ptr into the container. Because we have no way to warn the package container: copying Auto_PTR is unusual (ownership, and changing the status of the right object). In fact, all the compilers I know have gone this code and even as an example in their documentation. However, it is actually unsafe (and, it is not legal now).
The problem is that auto_ptr does not satisfy the object of the object to be placed in the type, because the copy of Auto_PTR is not equal. First, it is not said that vector must build a "additional" copy of the included object. Of course, usually you expect to do this copy (because it is not a must, and is inefficient, and based on competition, the seller does not like to provide an unnecessary inefficient library), but this is not necessarily, you You can't rely on it. Continue, because the error occurred:
v.push_back (new t (3));
v.push_back (new t (4));
v.push_back (new t (1));
v.push_back (a);
(Insert a: Note Copy A to Vector means the 'A' object is not there to have the pointer it carries. It will talk about it again.)
V.PUSH_BACK (New T (2));
Sort (v.begin (), v.end ());
in conclusion
| Before NJ After NJ
Legal? Yes NO
| SAFE? NO NO
This is really a nightmare, which is another reason for the Committee asking for amendment (the main reason for the auto_ptr in the draft 2). When you call the model function of the copy element (such as sort ()), this write function must assume that the copy is equal. For example, the Sort is at least a copy of a "current" element, and if you want it to work in Auto_PTR, it must have a copy of the current auto_ptr object (so take over its ownership and put it in a temporary auto_ptr object Middle) and continue to complete the rest of the work (including the copy of the auto_ptr object that is now no longer owned by ownership, as the current value), when the sort is complete, the tempolic object is destroyed, so the problem is coming: at least one of the sequence Auto_PTR (the one as a copy of the current value no longer has ownership of its inclusive pointer, in fact, this pointer has been delete!
The issue of auto_ptr in draft 2 is that it does not provide protection - no warning, nothing - to cope with such an error code. The Committee requires Auto_PTR or removes unusual copy semantics or makes these dangerous code unable to compile, so that the compiler can prevent you from doing dangerous things such as constructing a AUTO_PTR's Vector or trying to sort it.
Mining auto_ptr without ownership
// (after Having Copied a to another auto_ptr)
Cout << A-> Value ();
}
in conclusion
| Before NJ After NJ
Legal? Yes NO
| SAFE? (YES) NO
(We have already copied it, but its pointer is not deleted by Vector or Sort.) Under the draft, it is normal, because although it no longer owns ownership, Auto_Ptr still has a copy, but not in the range of survival Call DELETE as it knows it no longer ownership.
However, now, copying an auto_ptr is not only owned, but also sets the source Auto_PTR to NULL. This specially prevents anyone from doing anything through AUTO_PTR without the right. According to the final rules, this is illegal, and the results are undefined (the kernel DUMP is usually dumps under most systems.) In short:
Void f () {
Auto_PTR
Auto_PTR
PT1-> Value (); // using a non-ooning auto_ptr ...
// this buy to be legal, but is
// Now an error
PT2-> Value (); // ok
}
This is the final version of the common usage of Auto_PTR.
Package pointer member
Class c {
Public: /*...*/
protected: /*...*/
Private:
Auto_PTR
}
〖Note: An important detail on security is not mentioned in this item, it is seen in GotW # 62 and "Exceptional C "〗
in conclusion
| Before NJ After NJ
Legal? YES YES YES
| SAFE? YES YES YES YES
Auto_ptr Before, now, it is still a valid package for pointer members. It works very much like the example of our "background" in the beginning of the "background", just use the trouble of cope with the implementation of cleanup work in C, do not need to perform the trouble of cleaning work at the end of the function.
There is still a warning here, of course, like you still use the ordinary pointer member, you must handle the copy constructor and assignment function (even if it is used for private without defining their methods), Because the default version of the behavior is wrong.
Last News: The habitual usage of "cont AU_PTR"
Now let's enter a deeper level, you will find an interesting skill. In addition to other benefits, the hard AUTO_PTR is also illegally copied by CONST AUTO_PTR. E.g:
Const auto_ptr
// MAKING PT1 Const Guarantees That Pt1 CAN
// NEVER Be copied to another auto_ptr, and
// SO is Guaranteed to NEVER LOSE OWNERSHIP
Auto_PTR
Auto_PTR
PT3 = pt1; // illegal
This habit usage of this "const auto_ptr" may become one of the common techniques, and now you can say that you know it.
I hope that you like this period to dedicate the C standard ISO final draft 〖November 1997.
Note 1. In the initial problem, I forgot that there is no T * to Auto_PTR