C++ return local object
S开发者_运维百科everal co-workers and I are having a debate about what happens when a local variable (allocated on the stack) is returned from a C++ method.
The following code works in a unit test, but I believe that is only because the unit test is lucky and doesn't attempt to reuse the memory on the stack used by obj.
Does this work?
static MyObject createMyObject() {
MyObject obj;
return obj;
}
What happens is that the copy constructor gets called to make a copy of the local object, and that is what the caller receives.
The compiler may eliminate the copy in a process called copy elision, but that's at the discretion of the compiler - you don't have much control over it.
This pattern is capable of producing the problems you're afraid of, but only if you're returning a pointer or reference to the local object.
obj
is created, and then it is copied out of the method/function using the object's copy constructor.
You can make this obj
to not to be in the stack by declaring it static
too. Returning the object returns a copy too, but the object doesn't get created each time the function is called. Then, you can return the object as reference:
static MyObject & createMyObject() {
static MyObject obj;
return obj;
}
(no copy here, and also obj
is created only once, and its address remains constant at runtime).
You return the object by value, so it's copy constructor will be called, and a COPY of the original object will be returned and stored on the caller's stack. Should this method return a pointer (or reference) of a local variable it would fail.
A copy of MyObject is returned. Which should be fine if MyObject has a copy constructor that copies everything correctly. Note it may have a copy constructor even without explicitly listing one -- The compiler defined default copy constructor (which assigns everything memberwise) may work fine for your purposes.
In this example, MyObject is being returned by value. That means that a copy of it is made and passed back to the calling function. (In certain cases the compiler can optimize the spurious copy away, but only when that would be equivalent to calling the copy constructor on MyObject and placing the copy on the stack.)
Assuming everyone else simply missed an obvious source of confusion in this question -- static
:
You're not declaring the MyObject
instance created in and returned from createMyObject
as having static storage duration; rather, you're declaring the function createMyObject
as having internal linkage.
It's ok for a function to "return a local object", because the compiler will transform the function to not really return a value. Instead, it will accept a reference MyObject& __result
, and use the local object which will be assigned the return value, i.e. obj
, to copy construct the __result
. In your case, the function will be rewritten to:
static void createMyObject(MyObject& __result) {
MyObject obj;
// .. process obj
// compiler generated invocation of copy constructor
__result.MyObject::Myobject( obj );
return;
}
and every invocation of createMyObject
will also be transformed to bind the reference to an existing object. For example, an invocation of the form:
MyObject a = createMyObject();
will be transformed to:
MyObject a; // no default constructor called here
createMyObject(a);
However, if you return a reference or pointer to a local object, the compiler cannot fulfill the transform. You will be returning a reference or pointer to a already-destroyed object.
This works just fine. It will create a temporary anonymous variable that returns MyObject:
Anonymous variables and objects
binding a temporary object to a reference to const
精彩评论