std::move a stack object (to a different thread) - c++

So there are two things that I'm not sure.
If I do something like this:
void sendToDifferentThread(SomeClass &&obj);
...
{
SomeClass object;
sendToDifferentThread(std::move(object));
}
What will happen? How can there ever only be one copy of object if it's created on the stack, since when we go out of the enclosing scope everything on stack is destroyed?
If I do something like this:
SomeClass object;
doSomethingOnSameThread(std::move(object));
What will happen if I do something in the current scope to object later? It was "moved away" to some other function, so did the current function "lose" ownership of it in some way?

In C++ when an object is constructed, memory is allocated at the same time. If the constructor runs to completion (without throwing) then the object is "alive". At some point if it is a stack object and goes out of scope, or its a heap object and you call delete, its destructor is called and that original memory is freed, and then the object is "dead". C++11 std::move / move constructors don't change any of this. What a move constructor does is give you a way and a simple syntax to "destructively" copy objects.
For instance if you move construct from a std::vector<int>, instead of reading all the ints and copying them, it will copy the pointer and the size count instead to the new vector, and set the old pointer to a nullptr and size to 0 (or possibly, allocate a (tiny) new vector of minimal size... depends on implementation). Basically when you move from something you have to leave it in a "valid", "alive" state -- it's not "dead" after you move from it, and the destructor is still going to be called later. It didn't "move" in the sense that it's still following the same lifetime and now it's just "somewhere else in memory". When you "move" from an object, there are definitely two different objects involved from C++'s point of view and I don't think you can make sense of it after a certain point if you try to think of it as though there's only one object that exists in that scenario.

Related

What happens to "lost" stack objects?

Say Pokemon is a class. Consider this snippet:
Pokemon Eve(4,3); //call to constructor, creating first object on the stack
Eve=Pokemon(3,5); //call to constructor again, creating a second object on the stack
Both objects are created on the stack. After the second line executes, the first object (with parameters 4,3) can no longer be accessed. What happens to it? What is the jargon used to describe this process? Garbage collection?
I think you misunderstand what is happening. The object originally created as Eve isn't 'lost' after the second line. In fact, it is still the same object afterwards (by which I mean it still has the same memory address). The second line assigns a different value to the object by calling the assignment operator on the object Eve. The parameter passed to the assignment operator is the temporary object created by Pokemon(3,5).
It is the said temporary object - Pokemon(3,5) which is destroyed after the second line. Its destruction is not 'garbage collection' or even a heap deallocation, as it is a stack object in the first place and thus doesn't require such.
I think you're thinking about this in terms of Java/C# or similar managed languages, that only have object references and not direct objects. In C++ with the code above you're dealing with objects directly. To see something equivalent to what you have in mind, consider this:
Pokemon* Eve = new Pokemon(4,3);
Eve=new Pokemon(3,5);
Here we're using pointers and the heap, rather than the stack. In this case, the second line really does 'lose' the original object, because it is the pointer that is reassigned. This is sort of similar to what happens in Java/C# with just normal assignment. The difference is, of course, that C++ doesn't have any garbage collector so in the above the original object is truly lost in the sense of being a memory leak.
It's called "the assignment operator", or "=".
The second object is the temporary object, not the first one. After it is constructed, the first object's assignment operator is invoked, to assign the value of the second object to the first object.
After that the second object's destructor is invoked, and the second object gets destroyed. Where it goes? To the great bit bucket in the sky. It's gone.
The objects are not created on the heap, but directly on the stack, so no space is lost (i.e., there's no allocated space that becomes unreachable) -- the assignment simply reuses the memory allocated by the initialization of Eve.
Edited: More careful wording around the "overwriting" contention.

Create shared_ptr to stack object

In my method a Player object is created like:
Player player(fullName,age);
My teacher gave us a piece of code with a constructor that takes a shared_ptr to a player object.
//constructor of the class
SomeClass(const std::shared_ptr<Socket> client, std::shared_ptr<Player> player)
Lets say we want to call the constructor of SomeClass and pass the player object we created on stack.
Is it ever safe/possible/good to create a shared_ptr from a stack object?
To make the question more understandable lets say we have two big code projects and we want to merge them so a method from one project is called from another one, should we rewrite all the files to use shared_ptr or stack objects exclusivly (for the methods that needs to be connected) or should we just create a shared_ptr to the stack object.
Why im not sure of the result:
What if the scope where the stackobject is created ends but the shared_ptr is still used and vise versa.
The stackobject gets deleted when out of scope or does it stay alive because there is still a reference to the object (in another class though)?
The shared_ptr goes out of scope and tries to delete the object, can it even though the stackobject is refering to it?
Note: I know I could just use the following and pass player
shared_ptr<Player> player{ new Player {fullName,age} };
Is it ever safe/possible/good to create a smart_ptr from a stack object?
Safe? Only if you can guarantee that the stack which created that object will only be ended after all shared_ptr's that pseudo-own it.
Possible? Sure: pass shared_ptr's constructor a deleter object that does nothing:
auto sptr = shared_ptr<Player>(&player, [](Player *) {});
When the last shared_ptr is destroyed, the deleter will be called and nothing will be deleted.
Good? Not really. As noted above, safety is not something that can be universally guaranteed in such code. Depending on your code structure, this may be legitimate. But it requires great care.
This SomeClass is expecting to claim ownership of a resource; that's why it's taking a shared_ptr. You're kind of lying to it by passing it a shared_ptr that doesn't really own the object it references. That means the onus is on you and your code structure to not violate the promise you made to SomeClass that it would have shared control over that object's lifetime.
The purpose of a shared pointer is to manage the lifetimes of dynamically created objects. As long as there is any shared pointer that points at an object, that object must still exist; when the last shared pointer that points at an object is destroyed, that object gets destroyed.
Stack objects have a fundamentally different lifetime: they exist until the code exits from the scope in which they were created, and then they are destroyed.
The two notions of lifetime are incompatible: there is no way a shared pointer can ensure that a stack object that has gone out of scope still exists.
So don't mix the two.
Is it ever safe/possible/good to create a shared_ptr from a stack object?
I agree with #Nicolas Bolas that it is not safe. But it may be safe to create a shared_ptr from a copy of a stack object
shared_ptr<Player> playerPtr(new Player(player));
if Player is copy-able of course.
It's not safe to create a shared pointer to a stack object, because the stack object is due for destruction as soon as its containing function returns. Local objects are allocated and deallocated implicitly and automatically and trying to intervene is surely invoking many kinds of undefined behavior.
Use move semantics to create the shared_ptr
std::shared_ptr<Player> player_shared_ptr{ std::make_shared(std::move(player)) };
In this way, a copy is avoided. You may need to implement move constructor though on relevant classes for this approach to work. Most/all std objects support move semantics out of the box (eg. string, vector, etc.)
Safe is a strong word.
However, You can make the code safer by defining a StackObjectSharedPtr, forcing the shared_ptr instanciated type to include a "special" StackObjectDeleter
using PlayerStackSP = std::shared_ptr <Player, StackObjectDeleter> ;
class StackObjectDeleter {
public:
void operator () (void*) const {}
};
Player player(fullName,age);
std::shared_ptr<PlayerStackSP, StackObjectDeleter> player(&player, StackObjectDeleter());
The StackObjectDeleter replaces the default_delete as the deleter object. default_delete simply calls delete (or delete []). In case of StackObjectDeleter, nothing will happen.
This is a step further of #Nicol Bolas's answer.

Returning an object: value, pointer and reference

I know this has probably been asked and I've looked through other answers, but still I cannot get this completely.
I want to understand the difference between the two following codes:
MyClass getClass(){
return MyClass();
}
and
MyClass* returnClass(){
return new MyClass();
}
Now let's say I call such functions in a main:
MyClass what = getClass();
MyClass* who = returnClass();
If I got this straight, in the first case the object created in the
function scope will have automatic storage, i.e. when you exit the
scope of the function its memory block will be freed. Also, before
freeing such memory, the returned object will be copied into the
"what" variable I created. So there will exist only one copy of
the object. Am I correct?
1a. If I'm correct, why is RVO (Return Value Optimization) needed?
In the second case, the object will be allocated through a dynamic storage, i.e. it will exist even out of the function scope. So I need to use a deleteon it. The function returns a pointer to such object, so there's no copy made this time, and performing delete who will free the previously allocated memory. Am I (hopefully) correct?
Also I understand I can do something like this:
MyClass& getClass(){
return MyClass();
}
and then in main:
MyClass who = getClass();
In this way I'm just telling that "who" is the same object as the one created in the function. Though, now we're out of the function scope and thus that object doesn't necessarily exists anymore. So I think this should be avoided in order to avoid trouble, right? (and the same goes for
MyClass* who = &getClass();
which would create a pointer to the local variable).
Bonus question: I assume that anything said till now is also true when returning vector<T>(say, for example, vector<double>), though I miss some pieces.
I know that a vector is allocated in the stack while the things it contains are in the heap, but using vector<T>::clear() is enough to clear such memory.
Now I want to follow the first procedure (i.e. return a vector by value): when the vector will be copied, also the onjects it contains will be copied; but exiting the function scope destroys the first object. Now I have the original objects that are contained nowhere, since their vector has been destroyed and I have no way of deleting such objects that are still in the heap. Or maybe a clear() is performed automatically?
I know that I may beatray some misunderstandings in these subjects (expecially in the vector part), so I hope you can help me clarify them.
Q1. What happens conceptually is the following: you create an object of type MyClass on the stack in the stack frame of getClass.
You then copy that object into the return value of the function, which is a bit of stack that was allocated before the function call to hold this object.
Then the function returns, the temporary gets cleaned up. You copy the return value into the local variable what. So you have one allocation and two copies.
Most (all?) compilers are smart enough to omit the first copy: the temporary is not used except as return value. However, the copy from the return value into the local variable on the caller side cannot be omitted, because the return value lives on a part of the stack that is freed as soon as the function finishes.
Q1a. Return Value Optimization (RVO) is a special feature, that does allow that final copy to be elided. That is, instead of returning the function result on the stack, it will be allocated straight away in the memory allocated for what, avoiding all copying altogether. Note that, contrary to all other compiler optimizations, RVO can change the behaviour of your program! You could give MyClass a non-default copy constructor, that has side effects, like printing a message to the console or liking a post on Facebook. Normally, the compiler is not allowed to remove such function calls unless it can prove that these side effects are absent. However, the C++ specs contain a special exception for RVO, that says that even if the copy constructor does something non-trivial, it is still allowed to omit the return value copy and reduce the whole thing to a single constructor call.
2. In the second case, the MyClass instance is not allocated on the stack, but on the heap. The result of the new operator is an integer: the address of the object on the heap. This is the only point where you will ever be able to obtain this address (provided you didn't use placement new), so you need to hold onto it: if you lose it, you cannot call delete and you will have created a memory leak.
You assign the result of new to a variable whose type is denoted by MyClass* so that the compiler can do type checking and stuff, but in memory it is just an integer large enough to hold an address on your system (32- or 64-bits). You can check this for yourself by trying to coerce the result to a size_t (which is typedef'd to typically an unsigned int or something larger depending on your architecture) and seeing the conversion succeed.
This integer is returned to the caller by value, i.e. on the stack, just as in example (1). So again,
in principle, there is copying going on, but in this case only copying of a single integer which your CPU is very good at (most of the times it will not even go on the stack but get passed in a register) and not the whole MyClass object (which in general has to go on the stack because it's very large, read: larger than an integer).
3. Yes, you should not do that. Your analysis is correct: as the function finishes, the local object is cleaned up and its address becomes meaningless. The problem is, that it sometimes seems to work. Forgetting about optimizations for the time being, the main reason the way memory works: clearing (zero-ing) memory is quite expensive, so that is hardly ever done. Instead, it is just marked as available again, but it's not overwritten until you make another allocation that needs it. Therefore, even though the object is technically dead, its data may still be in the memory so when you dereference the pointer you may still get the right data back. However, since the memory is technically free, it may be overwritten at any time between right now and at the end of the universe. You have created what C++ calls Undefined Behaviour (UB): it may seem to work right now on your computer, but there's no telling what may happen somewhere else or at another point in time.
Bonus: When you return a vector by value, as you remarked, it is not just destroyed: it is first copied to the return value or - taking RVO into account - into the target variable. There are two options now: (1) The copy creates its own objects on the heap, and modifies its internal pointers accordingly. You now have two proper (deep) copies co-existing temporarily -- then when the temporary object goes out of scope, you are just left with the one valid vector. Or (2): When copying the vector, the new copy takes ownership of all the pointers that the old one holds. This is possible, if you know that the old vector is about to be destroyed: rather than re-allocating all the contents again on the heap, you can just move them to the new vector and leave the old one in a sort of half-dead state -- as soon as the function is done cleaning that stack the old vector is no longer there anyway.
Which of these two options is used, is really irrelevant or rather, an implementation detail: they have the same result and whether the compiler is smart enough to choose (2) should not usually be your concern (though in practice option (2) will always happen: deep copying an object just to destroy the original is just pointless and easily avoided).
As long as you realize that the thing that gets copied is the part on the stack and the ownership of the pointers on the heap gets transferred: no copying happens on the heap and nothing gets cleared.
Here are my answers to your different questions:
1- You are absolutely correct. If I understand the sequentiallity correctly, your code will allocate memory, create your object, copy the variable into the what variable, and get destroyed as out of scope. The same thing happens when you do:
int SomeFunction()
{
return 10;
}
This will create a temporary that holds 10 (so allocate), copy it to the return vairbale, and then destroy the temporary (so deallocate) (Here I'm not sure of the specifics, maybe the compiler can remove some stuff via automatic inlining, constante values, ... but you get the idea). Which brings me to
1a- You need RVO when to limit this allocation, copy, and deallocation part. If your class allocates a lot of data upon construction it is a bad idea to return it directly. You can use move constructor in that case, and reuse the storage space allocated by the temporary for example. Or return a pointer. Which takes all the way down to
2- Returning a pointer works exactly as returning an int from a function. But because pointers are only 4 or 8 bytes long, allocation and deallocation cost a lot less than doing so for a class that's 10 Mb long. And instead of copying the object you copy its adress on the heap (usually less heavy, but copy nonetheless). Do not forget it is not because a pointer represents a memory that its size is 0 byte. So using a pointer requires getting the value from some memory address. Returning a reference and inlining are also good ideas to optimise your code, as you avoid chasing pointer, function calls, etc.
3- I think you are correct there. I'd have to make sure by testing, but if follow my logic you are right.
I hope I answered your questions. And I hope my answers are as correct as can be. But maybe someone more clever than me can correct me :-)
Best.

Constructing object in freestore using "new ClassType(std::move(/*class_object*/))"

Beginner's question:
Class Quote {
public:
/* ..... */
virtual Quote* clone() const & {return new Quote(*this);}
virtual Quote* clone() && {return new Quote(std::move(*this));} // (***)
/* ..... */
}
Objects allocated by new are in the free-store. *this is whatever object that calls clone() and is not necessarily a dynamically-allocated object.
How does the move mechanism work if the moved-from and moved-to objects are in different memory areas? Or perhaps they're never really in different areas and I'm missing something?
From what I understand, the move constructor creates new overheads that link to the data/memory part of the moved-from object. The data itself is not moved/changed. How does this work in the above case? If it works the same way then after new runs wouldn't we have a dynamically-allocated object that sit outside free-store (wherever *this is located?) Is this somehow resolved by std::move()? I'm not exactly sure how/why std::move() work besides that it force-returns an rvalue reference to a named object making it possible to move from that object.
From what I understand, the move constructor creates new overheads
that link to the data/memory part of the moved-from object. The data
itself is not moved/changed.
Not true. A typical move constructor ((I emphasize typical because a move constructor can really do anything the class writer wants it to do) will "steal" resources which another object owns remotely (e.g. a dynamically allocated array), by reassigning handles (e.g. a pointer to a dynamically allocated array)
When I say the resource is owned remotely, I mean it is not actually a data member of the class. The handle, however, is a data member of the class. The handle refers to the resource. The moved to object and the moved from object have distinct addresses and data members. Their data is able to be moved efficiently because it is not actually part of the class, it is referred to by the handle. The handle, unlike the resource, is small, and cheap to copy. "Moving" is actually copying handles from a source object to a destination object, then nullifying the handles in the source object so that its destructor doesn't destroy the resource.
How does the move mechanism work if the moved-from and moved-to
objects are in different memory areas?
(Again I am speaking of a typical move constructor) It's irrelevant. Wherever they happen to be stored, they still have the same memory layout. The handles are modified exactly the same. The resource will be released when the destructor of the moved-to object is called (unless that object too is moved from). That means either when the object goes out of scope, if it is on the stack, or when delete is called on a pointer pointing to it, if it is on the free-store. (There are other possibilities, but those two are obviously the most common)
A move does not move everything. Builtin data types like ints and pointers, for example can't be moved, they just can be copied. Moving is pure semantics. Best example is a std::vector or a std::string. Both typically contain a pointer to some dynamically allocated memory and some other variables. Said memory semantically belongs to the vector object, meaning it has to free the memory, it may alter its contents, it has control over it and is the only one to do so. The common term is "the vector has ownership of the allocated memory".
Now, when you copy a vector, the original will keep that ownership, and the copy will have to allocate it's own memory. In contrast, when you move a vector, the move-constructed new vector is allowed to steal the allocated memory, taking over the ownership of the resource the original vector once posessed. This can be done because the original vector is about to go out of scope anyways, and it does not need that resource any more.
However, the actual data members of the moved vector are not moved themselves. Since they are pointers and maybe ints, they can only be copied. After that has been done, the pointers and ints in the original get changed in a way that semantically ends its ownership of the allocated memory.
In short: moving is a semantic thing, on the lower technical level it is mostly a copy and setting the original to zero.

Do you call delete in destructor in C++?

Let say you have a class like this
class Level
{
public:
Level(std::string);
~Level();
private:
Bitmap* map;
}
and in the class you had this
Level::Level(std::string)
{
map = new Bitmap(path);
}
Was wondering do can you call
Level::~Level()
{
delete map;
}
As I was worried about if the class goes out of scope and I haven't deleted map. Then, wouldn't that cause a memory leak. Do I have to manually call to delete map. As I get crash if I call delete in the constructor in my program.
Like I could add a method to Level called say destroy map where I delete map. But, was wondering why I can't add delete into the destructor.
When the Level object goes out of scope, its destructor will be called, so deallocation of memory is useful because that memory is no longer needed. You can also use a unique_ptr, whereby memory-deallocation performed automatically.
This is why destructors stand for. Destructor is explicitly called when your object goes out of scope (memory residing on the stack objects) or when delete is called ( for dynamically allocated objects), so that the memory the object kept would be released. If you want to release member objects memory when destroyed, you can call the destructors of each object using delete (or delete[] for arrays). It is better that you use smart pointers, to avoid unintentional memory leaks and to ensure the memory is freed correctly in all cases, as they use RAII concept (RAII and smart pointers in C++).
Answers already have pointed out that you can trust your destructor to be called when your object goes out of scope. I won't reiterate that. I just wanted to point out that there is no need to allocate your Bitmap with new (unless you were using custom memory allocators, which is not the case here). You can construct it with an initialiser list:
class Level
{
public:
Level(std::string);
private:
Bitmap map;
};
Level::Level(std::string)
: map(path)
{
}
Now it has automatic scope and you don't have to worry about your destructor.
That's basically right.
However:
You need to make sure you create a copy constructor and assignment operator too, if you are managing memory this way. (That's where your crash comes from.)
An alternative, the best way, is to use RAII and store not a raw pointer but a scoped or automatic pointer. Or even just a directly encapsulated object! Then you don't need the delete at all.
As I was worried about if the class goes out of scope and I haven't deleted map. Then, wouldn't that cause a memory leak.
You're right - you should delete map exactly as your code does. But, you should also make your object non-copyable (derive from boost or C++11 noncopyable base classes, or add a private declaration (with no definition/implementation) of the operator= copy assignment and copy constructor. Otherwise, if you (deliberately or accidentally or incidentally - e.g. when storing your object in a container that sometimes copies it around, such as a std::vector) copy your object, then the first copy destructored will delete the map, any other copy that tries to use it will likely crash, and any other copy's destructor that also tries to delete it will also have undefined behaviour.
Do I have to manually call to delete map.
Yes, in your code you do.
A better alternative is to use a smart pointer whose own destructor will delete the pointed-to object.
As I get crash if I call delete in the constructor in my program.
Well, if you call delete after the new, then the constructor won't crash, but you wouldn't have a map object to use after the constructor returns, and if you then try to delete it again in the destructor the you get undefined behaviour which may well manifest as a crash.
If you want to delete the map earlier than the destructor sometimes, you can set the pointer to NULL so that a future delete will do nothing safely. You should then check for NULL before trying to use the map.
Like I could add a method to Level called say destroy map where I delete map. But, was wondering why I can't add delete into the destructor.
As above, you can have destroy_map, but it must coordinate with the destructor.
When there's no compelling reason to do otherwise, it's better to make the map member data, not storing it by reference. When a pointer is useful, use a smart pointer if at all possible. If you want to implement explicit manual memory management, be wary of the issues above.
This is an unusual way to do it. Normally, an object's lifetime is determined by factors outside of the object.
But in fact MFC used to (still does?) do exactly this when a Window is being destroyed. (In response to WM_NCDESTROY, I believe.) This ensures you don't have the Window instances leaking memory after the window is gone.
So I would say it is valid in some cases. You might call it class suicide!