A bug about temporary object
Translation: Bug translation from WDN in June 2003, there is a reduction.
I believe that any programmer who uses C more than a certain period of time will not deny this fact: there is enough skill to use C . It is full of a variety of difficult-related traps that can make a code that looks no flaws. For example, for the newcomers of C / C , learn how to consider the living period of the object is an obstacle that they must leapfrively, this is the most typical problem, which is the use of object pointers, especially when using a already deleted. When the object pointer:
Myclass * mc = new myclass;
// do some stuff
Delete MC;
MC-> a = 1; // uh oh ... MC is no longer valid!
Some more mysterious things happen when the function returns, we assume a function, such as foo () returns an object reference for a MyClass type:
Myclass & foo ()
{
Myclass mc;
// do some trings
Return MC;
}
This problematic code is actually completely legitimate. When the function foo () life is not over, the MC will be destroyed, but the function returns a reference, so that the function The caller will get a reference, it points to a no object, if you are lucky enough, you may get a warning from the compiler (for example, VC 7.0 will give such a warning: "Warning C4172: Returning Address of Local OR Temporary. "), but notice that every compiler will be so friendly.
This is a very common example. I believe that each C programmer has made at least once such a mistake. However, for the temporary object of C , things become a bit more complicated. If I change the definition of foo, let it return to a copy of an object, not a reference, what happens?
Myclass foo ()
{
Myclass mc;
Return MC;
}
Now, when foo returns, it will generate a temporary object, which will be assigned a variable specified by the call function. In order to see how this happens, let's take a look at the results of the Listing 1 code:
Default Constructionor
Copy Constructor
Destructor
Returned from foo
Destructor
Listing 1 Function Returning a Temporary Object
// Demonstrates Returning a Temporary Object.
#include
Using namespace std;
Class myclass
{
PUBLIC:
Myclass (const myclass &)
{COUT << "Copy Constructor / N";
Myclass ()
{COUT << "default constructor / n";
Myclass & operator = (const myclass&)
{
Cout << "ASSIGNMENT OPERATOR / N";
Return * this;
}
Myclass :: ~ myclass () {
Cout << "deStructor / N";
}
}
Myclass foo ()
{
Myclass mc;
// Return A Copy Of MC.
Return MC;
}
int main ()
{
// this code generates the temporary
// Object Directly in the location
// of retval;
Myclass rv1 = foo ();
// this code generates a Temporary
// Object, Which Then IS Copide
// INTO RV2 Using The Assignment
// Operator.
// myclass rv2;
// rv2 = foo ();
COUT << "Returned from foo / n";
Return 0;
}
You may think that there is an object to be lost here. After all, if you look at the pseudo code, you will think that something should happen:
In FOO, the MC is declared, which calls the default constructor, then the foo returns a temporary object, this temporary object is a copy of the MC, and therefore calls the copy constructor, this temporary object is assigned RV1 and call the copy constructor again.
But please wait, we check the output of the app, the copy constructor is only called once! There should be three objects to generate: MC (in the FOO function), a temporary object, and RV1. Why not call three constructor? The answer to this question is: The code optimization of the C standard is optimized to deceive us, the purpose of doing this is to avoid the code too inefficient, if a temporary object is used as a return value to another object, this temporary object itself will be Constructed to the location of the assigned object in memory. This avoids a unnecessary constructor call. When constructor needs to do a lot of initialization work, this can save a lot of time (if you are interested in this area, please refer to Section 12.2, paragraph 3 of C ). ).
There is another related example, for example, when RV has been declared:
Myclass rv;
RV = foo ();
At this time, the temporary object will not be constructed to the RV position, because the RV has been constructed when the FOO call is happened, so this temporary return value must be constructed as an independent object, and then assign a value RV. In fact, if you open the comments in the Listing 1 code, you will get some expectations (the comments in parentheses are me plus):
Default Constructionor (RV2)
Default Constructionor (MC)
Copy Constructor (Temporary)
DESTRUCTOR (MC)
Assignment Operator (RV2 = Temporary)
Destructor (Temporary)
Returned from foo
Destructor (RV2)
Here, it is important to note that the temporary object is destroyed when it is generated, in other words, the destructor will be called at the end of this sentence:
RV = foo (); // Temporary is destroyed here