Several 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
Related
look at my code:
#include <iostream>
using namespace std;
class MyClass{
public:
char ch[50] = "abcd1234";
};
MyClass myFunction(){
MyClass myClass;
return myClass;
}
int main()
{
cout<<myFunction().ch;
return 0;
}
i can't understand where my return value is stored? is it stored in stack? in heap? and does it remain in memory until my program finished?
if it be stored in stack can i be sure that my class values never change?
please explain the mechanism of these return. and if returning structure is different to returning class?
MyClass myClass; is stored on the stack. It's destroyed immediately after myFunction() exits.
When you return it, a copy is made on the stack. This copy exists until the end of the enclosing expression: cout << myFunction().ch;
Note that if your compiler is smart enough, the second object shouldn't be created at all. Rather, the first object will live until the end of the enclosing expression. This is called NRVO, named return value optimization.
Also note that the standard doesn't define "stack". But any common implementation will use a stack in this case.
if returning structure is different to returning class?
There are no structures in C++; keyword struct creates classes. The only difference between class and struct is the default member access, so the answer is "no".
It's up to the implementation to find a sensible place to store that value. While it's usually on the stack, the language definition does not impose any requirements on where it's actually stored. The returned value is a temporary object, and it gets destroyed at the end of the full statement where it is created; that is, it gets destroyed at the ; at the end of the line that calls myFunction().
When you create an object in any function it's destroyed as soon as the function execution is finished just like in variables.
But when you return a object from a function firstly compiler creates a local instance of this object in heap called unnamed_temporary then destroyes the object you created. And copies the contents of unnamed_temporary on call. Then it destroyes this unnamed _temporary also.
Anything you create without the keyword new will be created in stack.
Yes,contets of your variable ch will not change unless you access that variable and change it yourself.
The instance returned by myFunction is temporary, it disappears when it stop to be useful, so it doesn't exist after after the cout <<.... Just add a destructor and you will see when it is called.
What do you mean about can i be sure that my class values never change? ? You get a copy of the instance.
returning structure is different to returning class? : a struct is like a class where all is public by default, this is the alone difference.
Your function is returning a copy of an object. It will be stored in the stack in memory.
The returning obj. will exist until the scope of that function. After that, it will be destroyed. Then, your expression cout<<function(); will also have the copy of that obj. which is returned by the function. IT will be completely destroyed after the running of this cout<<function(); expression.
I know in C++ that a pointer is just that: a pointer to a memory location, and there is no concept of "owners". But consider the following situation (not necessarily good code):
class A {
public:
A(){}
~A()
{ if(myObject!=nullptr)
delete myObject;
}
void createMember()
{myObject=new CrazyCustomClass();}
CrazyCustomClass *getMember()
{return myObject;}
private:
CrazyCustomClass *myObject=nullptr;
}
If it makes a difference, CrazyCustomClass does NOT have a copy constructor, as it makes no sense to copy it. So pretty straight forward - I have a class that, at some point after instantiation, may call new to instantiate a member of type CrazyCustomClass *
The problem is that if at some point I have a copy of class A created (which is fine - I want to be able to copy class A). When that copy is deleted, so is the object pointed to by the original class A instantiation. For example:
void StupidFunction(A *firstObject){
//This is NOT a real function, it simply illustrates the effect of a third-party library function
//create a new object that is a copy of first object
A secondObject(*firstObject);
<do whatever with second object>
//secondObject goes out of scope here and gets deleted.
}
A *firstObject=new A();
firstObject->createMember();
stupidFunction(firstObject);
CrazyCustomClass *customObject=firstObject.getMember(); //this is now an invalid pointer
In the above example, the StupidFunction is from a third-party library, the idea being that it gives a "temporary" copy of the object that you can work with without messing with the original object, which is good. Class A and CrazyCustomClass are both my code and can be changed at will. Unfortunately, when the "temporary" copy is deleted, the way I wrote my destructor causes problems.
My first thought was to use shared_ptr, something like so:
std::shared_ptr<CrazyCustomClass> sharedObject=std::make_shared<CrazyCustomClass>(new CrazyCustomClass);
...but that gave me an error when compiling:
candidate constructor (the implicit copy constructor) not viable: no
known conversion from 'CrazyCustomClass *' to 'const CrazyCustomClass'
for 1st argument; dereference the argument with *
and if I do dereference the argument with *, it gives me an error about the copy constructor of "CrazyCustomClass" being deleted, which is true - there is no sensible way to copy CrazyCustomClass.
So my question is: how can I refactor class A such that myObject gets properly deleted when firstObject goes out of scope, but not when any "temporary" copies of A get deleted?
Using a shared_ptr is in fact a solution to this problem, however the code as attempted in the original question is incorrect. There are two (at least) different ways to initialize a shared_ptr (ref: https://msdn.microsoft.com/en-us/library/hh279669.aspx). First, you can do it by using new as a constructor argument:
shared_ptr<CrazyCustomClass> myObject(new CrazyCustomClass)
Secondly, and this is the generally preferred method, you can use the make_shared function (as attempted in the original post), which takes not the new object, but the arguments to be passed to the object constructor, in this case nothing:
shared_ptr<CrazyCustomClass> myObject=make_shared<CrazyCustomClass>()
The original code simply got these two methods mixed up, thus the errors about copy constructor: it was trying to instantiate a new CrazyCustomClass object with a pointer to a CrazyCustomClass object as the constructor argument.
Once using a shared_ptr, the delete in the destructor must be removed.
Tip of the hat to #tkausl and #alterigel for pointing out the error in the comments on the question!
I have function in c++ with 2 optional c'tor of an object I've built (one with something in vector "vals" and other without).
...
RecievedMessage a(sc, type);
if (!vals.empty()){
//a.~RecievedMessage();
RecievedMessage a(sc, type, vals);
}
return &a;
}
the line in // is optional.
Would it work (with or without the optional line)? Why? If no, how to fix it without setter for "vals"?
thanks a lot.
No, it wouldn't work.
RecievedMessage a(sc, type);
// Here we construct 'a'
if (!vals.empty()){
//a.~RecievedMessage();
// If we enable this line, we destroy 'a'
RecievedMessage a(sc, type, vals);
// Here we construct a second 'a' that only exists in this block
}
// End of block: The inner 'a' is destroyed here automatically
return &a;
}
// End of block: The outer 'a' is destroyed here, again.
Destroying an object twice has undefined behavior. You don't want that.
If you don't call the destructor manually, the outer a is only destroyed once, which is good.
But in either case, RecievedMessage a(sc, type, vals); has nothing to do with the outer a and merely creates another variable.
There would be ways to work around that, but the final line of your code makes it all pointless:
return &a;
You're returning the address of a local variable. This is broken in and of itself: When the function returns, all of its local variables are destroyed automatically, so what you're returning is an invalid pointer.
Your code is all over the place, but what I think you're looking for is something like this:
ReceivedMessage *MakeReceivedMessage (foo sc, bar type, vector<whatever>& vals)
{
if (vals.empty())
return new ReceivedMessage (sc, type);
return new ReceivedMessage (sc, type, vals);
}
Of course, it would be better in this example to just have a single constructor and have the object test whether vals is empty when appropriate, but, in general, you can call whatever constructor you like whenever you like. Just manage your object lifetimes properly (and don't - ever - return a pointer to an object on the stack).
Example usage (to manage the lifetime of the object returned properly):
std::unique_ptr<ReceivedMessage> MyReceivedMessage (MakeReceivedMessage (...));
MyReceivedMessage->DoFunkyStuffWithMessage ();
....
Or, as melpomene points out, you can return a std::unique_ptr<ReceivedMessage> in the first place. Some (many?) would prefer that. You can construct it with std::make_unique.
There are three main issues with your code right now:
First of all, your commented out call to the destructor ~ReceivedMessage() should not be there at all. In C++, the destructor of objects is automatically called when an object's lifetime ends (either when it goes out of scope, or when delete is called if it was dynamically allocated with new). While there are some situations where explicitly calling a destructor is necessary ("placement new" for example), these are situations you're very unlikely to come across.
Secondly, your RecievedMessage a(sc, type, vals); declaration in the inner if does not replace the value of a in the outer scope. This just creates another variable of the same name which shadows the outer a, while return &a; in the outer scope can only refer to the outer a. The inner a no longer exists at this point as it has gone out of scope.
A way to fix this issue is to instead assign a new value to a by using the = operator and constructing a temporary ReceivedMessage:
if (!vals.empty()) {
a = ReceivedMessage(sc, type, vals);
}
This should work as long as a correct operator= is defined (implicitly or otherwise) for ReceivedMessage.
Thirdly, your function is returning a pointer to the local variable a. Since objects in C++ are destroyed as soon as they go out of scope, a no longer exists by the time the function has returned, so the ReceivedMessage * pointer the calling code obtains is invalid and it would be undefined behaviour to dereference that pointer and make use of it.
There are a couple of fixes to this issue:
The first option is instead of returning a pointer (ReceivedMessage *), just return a ReceivedMessage by value.
ReceivedMessage foo()
{
ReceivedMessage a(123);
return a;
}
This should work as long as a correct copy or move constructor is defined (implicitly or otherwise) for ReceivedMessage.
The second option is to make use of std::unique_ptr, and make your function instead return std::unique_ptr<ReceivedMessage>.
#include <memory>
std::unique_ptr<ReceivedMessage> foo()
{
std::unique_ptr<ReceivedMessage> a;
if (vals.empty()) {
a = std::make_unique<ReceivedMessage>(sc, type);
} else {
a = std::make_unique<ReceivedMessage>(sc, type, vals);
}
return a;
}
The advantage to this approach is that unique_ptr is nullable, so you can create a null unique_ptr without having to construct a ReceivedMessage straight away. Additionally, you can move and assign unique_ptr values safely without having a correct operator= or a correct copy / move constructor defined.
The calling code may look like this, when using unique_ptr:
std::unique_ptr<ReceivedMessage> message = foo();
foo->bar();
as opposed to the following when using ReceivedMessage directly:
ReceivedMessage message = foo();
foo.bar();
TestObject getObject(){
TestObject a(5.0f);
return a;
}
int main(){
TestObject a = getObject();
}
Am I right in saying that in C++ a returned object will not have it's destructor called as it is returned. Is the memory that the object took up in the function call simply deleted without running the destructor?
Ok a specific example..
#include <iostream>
class Test{
public:
Test(){};
~Test(){std::cout << "Goodbye cruel world\n";}
};
Test getAnObject(){
Test a;
return a;
}
int main(){
Test a = getAnObject();
}
If I run this the destructor is run just once (not for the local object in getAnObject()). Can I assume this will always be the case?
#include <iostream>
class Test{
public:
Test(){};
~Test(){std::cout << "Goodbye cruel world\n";}
};
Test getAnObject(){
Test a;
Test b;
int i = 0;
if (i){
return a;
}else{
return b;
}
}
int main(){
Test a = getAnObject();
}
Following the RVO guide this test has the destructor run on both objects in getanobject() and in the main function. Is this a case where I should always implement rule of three to ensure consistent behaviour?
If I run this the destructor is run just once (not for the local object in getAnObject()). Can I assume this will always be the case?
For correctness? No. For efficiency? Yes. -ish.
To elaborate: strictly speaking, the local object will be copied when returning from the function. The local storage will then be cleaned up by calling the local object’s destructor.
However, the compiler is free to generate different code that yields the same observable behaviour. In particular, the standard grants the compilers the right to elide the copying of the return value, and reuse the same storage location for both objects (the local object and the receiving object of the return value). In doing so, the compiler might not need to call the copy constructor, nor the destructor (since it’s reusing the same memory location).
However, this optimization (called “named return value optimization”, NRVO) is not guaranteed by the standard (and in fact it’s not possible to perform everywhere). You cannot assume that it will happen for correctness. In particular, your object still needs a well-defined copy constructor and destructor, otherwise the program is ill-formed.
On the other hand, you can reasonably expect all modern compilers to perform this optimization where ever it is possible. You can therefore (usually) rely on this optimization from a performance point of view.
It is implementation based. It is knows as Return Value Optimization technique. Check this out for more info:
http://en.wikipedia.org/wiki/Return_value_optimization
getObject() would return a copy of a. Here is what happens if the compiler does not do any optimization. A temporary copy of a will be created using the copy constructor of TestObject. Then the original a will be destroyed, and its destructor will be called, and then the temporary object will be copied into the local variable a in the main() function. The temporary will then also be destroyed, and its destructor will be called.
Since the return value of getObject() is immediately assigned to a variable in this particular case, a modern compiler will probably be able to optimize away at least one of the copy operations.
getObject() would return a copy of a, and the original object created in getObject is destroyed on exiting the function, but there can be Return Value Optimization (depends on the compiler you're using).
Besides the mismatched return types in the example, you are probably looking for return value optimization, or more general, copy elision. If I remember correctly, the copy elision rules are even specified in the C++ standard, although somewhat vague.
Is the memory that the object took up in the function call simply deleted without running the destructor?
No. With optimizations disabled, the local object will be destructed (and the destructor invoked). If a copy-elision optimization takes place, the local object will really just be a "reference" (note the quotes) for the one in main - in that case the destructor will not be run within the function, but the memory will not be de-allocated either.
In getObject, you are creating TestObject on the stack, so the return value is invalid. To create an object on the heap, use "new". I don't believe the destructor is called when the method's scope is exited, I think the memory on the stack is simply reclaimed.
i have the function: const A& f(...) {...}
a. const A a1 = f(..);
b. const A &a2 = f(...);
which of the is the better one to use? in both cases, if i understand correctly, i prevent the possibility of modifying the returned object.
in the first option, the copy constructor of A will be called - am i correct?
It depends on what you want.
In the first case you create a new const object that is constructed from the returned reference. It will be a snapshot of what was returned and will be valid for its entire lifetime.
In the second you just initialize a reference. This means that any changes to the original object will be visible through the reference but there is a danger that the referred object will be destroyed while the reference is still alive.
Yes, I prefer the second option as it prevents the copy being created.
You are correct the above copies. The lower does not.
The second one is the preferred one.
(Updated)
You should return by reference if the function is a method of a class and you are returning a reference to one of the members of that class. If you are creating the object in the function and then returning a reference to it, you are returning a reference to an object that doesn't exist anymore--when the stack unwinds, the object created in that function is destroyed.
You could also do it this way:
A someA;
f(someA); // Assuming that f's signature is void f(A&)
Or this way:
auto_ptr<A> someA = f();