State of object after std::move construction - c++11

Is it legal/proper c++0x to leave an object moved for the purpose of move-construction in a state that can only be destroyed? For instance:
class move_constructible {...};
int main()
{
move_constructible x;
move_constructible y(std::move(x));
// From now on, x can only be destroyed. Any other method will result
// in a fatal error.
}
For the record, I'm trying to wrap in a c++ class a c struct with a pointer member which is always supposed to be pointing to some allocated memory area. All the c library API relies on this assumption. But this requirement prevents to write a truly cheap move constructor, since in order for x to remain a valid object after the move it will need its own allocated memory area. I've written the destructor in such a way that it will first check for NULL pointer before calling the corresponding cleanup function from the c API, so that at least the struct can be safely destroyed after the move.

Yes, the language allows this. In fact it was one of the purposes of move semantics. It is however your responsibility to ensure that no other methods get called and/or provide proper diagnostics. Note, usually you can also use at least the assignment operator to "revive" your variable, such as in the classical example of swapping two values.
See also this question

Related

CPP guidelines: Reseating a smart pointer

R.33 is confusing me. Can someone care to explain further? The meaning of "reseating" doesn't seem to work here. ??
R.33: Take a unique_ptr& parameter to express that a function reseats thewidget
Reason Using unique_ptr in this way both documents and enforces the function call’s reseating semantics.
Note “reseat” means “making a pointer or a smart pointer refer to a different object.”
Example
void reseat(unique_ptr&); // "will" or "might" reseat pointer
Example, bad
void thinko(const unique_ptr&); // usually not what you want
From the CPP guideline:
"reseat" means "making a reference or a smart pointer refer to a different object."
From modernescpp.com:
Let's look at each function signature in isolation. What does this
mean from the function perspective?
void share(std::shared_ptr<Widget> shaWid)
I'm for the lifetime of the function body a shared owner of the
Widget. At the begin of the function body, I will increase the
reference counter; at the end of the function, I will decrease the
reference counter; therefore, the Widget will stay alive, as long as I
use it.
void reseat(std::shared_ptr<Widget>& shaWid)
I'm not a shared owner of the Widget, because I will not change the
reference counter. I have not guaranteed that the Widget will stay
alive during the execution of my function, but I can reseat the
resource. A non-const lvalue reference is more like: I borrow the
resource and can reseat it.
void mayShare(const std::shared_ptr<Widget>& shaWid)
I only borrow the resource. Either can I extend the lifetime of the
resource nor can I reseat the resource. To be honest, you should use a
pointer (Widget*) or a reference (Widget&) as a parameter instead,
because there is no added value in using a std::shared_ptr.

move semantics with temps allocated with new

I'm just wondering if move semantics are restricted to syntax style B.
More specifically, with style B the object is created on the stack and moved. With style A, the object is created on the heap, but it seems can't be moved.
The question very specifically is, can you use move semantics such that the temp is created with NEW? If so, how?
//move c'tor
A(A&& other) : num(other.num), s(other.s){
other.num = 0;
other.s = nullptr; //dyn alloc obj
}
If you do this, it doesn't work (syntax style A).
A a2(new A("blah")); //error
A a2(move(new A("blah"))); //error
This is ok (syntax style B)
A a2(A("blah")); //uses c'tor once
A a2(move(A("blah"))) //uses c'tor followed by move c'tor
You seem to be confused about a number of things, so I'll try to shed some light. You probably know most of this already.
Move semantics were designed to allow objects to transfer ownership of their data to another object. This was motivated largely to avoid copying from temporary objects that didn't need it.
The move constructor is much like the copy constructor, A(const A&), but only accepts a non-const xvalue of the same type, A(A&&) (think of it as an expiring value). Therefore, this constructor can be invoked when given something like a return value from a function or a variable moved via std::move.
Now, the function std::move in itself is a bit of a misnomer, it doesn't actually do anything. All it does it cast a T or T& into a T&&.
To address your question directly, nothing I've mentioned is specific to where the moving object is located, but it is specific about the types. A("blah") calls the constructor with automatic memory and returns that A. new A("blah") on the other-hand calls the constructor with dynamic memory and returns a pointer to that A, ergo an A*. So your syntax A is not trying to invoke the move constructor, but another constructor like A(A*).
To move from an object referenced by a pointer, all you need to do is derefence and move:
A* a1 = new A("blah");
A a2(std::move(*a1));
There's nothing stopping you from defining a constructor like A(A*), but that shouldn't be needed and isn't recommended for using move semantics.
Also, your syntax B comments are incorrect; both are a value-constructor A("blah") followed by the move-constructor A(A&&); the std::move doesn't add anything here.

Why is my lambda capturing a pointer by value?

I have the following lambda
direction->addClickEventListener([=](Ref* sender){
std::unordered_map<int,int> data;
rep->getData(DIRECTION, data);
int last = data[1];
int rotation = (last + 45)%360;
LOG("l:%i r:%i",last,rotation);//Always logs l:0 r:45
direction->setRotation(rotation);
data[1] = rotation;
rep->setData(DIRECTION, data);
});
where getData is:
void getData(DATA_KEY key,std::unordered_map<int,int>& data){
//Modifies data with the appropriate values for key, for the current state of rep
}
void setData(DATA_KEY key,std::unordered_map<int,int>& data){
//Makes a copy of data stores it internally with key
}
rep is pointer, so I thought that whenever the lambda is called, the current value of data will always reflect the current state of rep. But it seems that it is always the value of whatever rep was at the time direction->addClickEventListener was called.
If I want to use the current state of rep, how ghouls I modify my lambda ?
EDIT: Since rep is a pointer, I can't can't capture by reference..
I'm not really sure what you're asking, so this might not be an answer to your problem, but it is an attempt to clarify what the problem with capturing by reference is.
It looks like you are having an event-based system. The important thing to know about events is that they can occur at any time.
Now lets say you have something like this (very simplified and pseudo-ish):
void some_function(some_type* rep)
{
add_event_listener([&]()
{
do_something(rep);
});
}
There is a very serious bug in the code above: When the event is invoked and the lambda is called, the function some_function will have returned, and therefore the scope of the local variable rep doesn't exist any more. So when rep is used in the lambda it is a reference to a variable that doesn't exist anymore (remember that rep is a local variable). That of course leads to undefined behavior.
If you capture by value instead, the pointer is copied meaning you now have two pointer variables, both pointing to the same memory. Then it doesn't matter if the first variable goes out of scope, because the second variable still is valid.
Pointer doesn't have state, methods or something. Pointer is abstract address of storage where your object is. "Reference" is synonymous to pointer in some ways, if you think in C terms, but they are different in C++ - you can pass pointer variable by reference, thus passing control over its value (not over the state of object it points to, that actually achieved by pointer). Pointer variable is also a storage, that contains value of pointer
You can pass any variable (storage) "by reference", which means that function can change value stored in that variable. In C that was done by passing pointers, but to pass pointer "by reference" they had to pass type like void** pointer to a pointer. In C++ & syntax is used to reduce the clutter.
[=] mans that all external variables are captured by value. This would allow anonymous function to read value of pointer, deference it and call methods\access fields of the objects it points to.
[&] would mean capture by reference. Pointer is variable. This would allow lamba to modify it, making it to point to other object.
If you do need only rep by reference use, [=. &rep].
How rep might be changed while lambda is running? If that happens in parallel thread, you'll probably need an atomic.
If you cannot change actual object your pointer refers to, that may mean that compiler does aliasing optimization because of illegal cast from one object to another, because casted away const modifier or low quality of implementation (that's rare) that causes aliasing optimization where it should not happen.

interface function getting rvalue pointers to initialize shared_ptr

I have a class exposing through it's interface add function:
void AddObject(Object *o);
Inside the class I maintain the objects in set<shared_ptr<Object>>.
Since I will create shared_ptr from the received pointer I thought to limit the function argument to only rvalue pointers so to make sure that the user will not delete the pointer I use. And so I'll change the function declaration to:
void AddObject(Object* &&o);
so a typical use will be:
AddObject(new Object())
preventing the user to accidentally delete pointer I hold.
I don't want to to use shared_ptr in the interface because the user is not familiar with shared_ptr.
Do you think my suggestion is a good idea?
I think this is a bad idea. I'm sure there is a reason why shared_ptr c-tor that gets a raw pointer is marked explicit instead of using r-value. In my eyes, It's better to teach the users once about smart pointers or at least teach them about using make_shared/make_unique (which are safer and, in the case of make_shared, more efficient, BTW).
BTW, why shared_ptr and not unique_ptr?
Also, why set? Even if you want to make sure you hold each pointer only once and searching a vector each time doesn't look natural enough in your code, I don't see a reason to hold the pointers sorted instead of using unordered_set.
First of all, this approach will not prevent the user from deleting the pointer. Consider this example
auto obj = new Object();
AddObject(std::move(obj));
delete obj;
Secondly, the amount of steps between calling new and the creation of shared_ptr should be as few as possible. If anything happens inside AddObject before it can create a shared_ptr, the object will never get deleted.
The same applies if there are more arguments to AddObject(). If constructing those fails, you will leak memory.
void AddObject(Object* &&o, SomeOtherObject* x);
AddObject(new Object(), xx()); // if xx() throws, memory leak will occur
Ideally you would "wrap" object creating into shared_ptr construction:
void AddObject(std::shared_ptr<Object> o);
AddObject(std::make_shared<Object>());
Either of the following methods may solve your problem.
You may append more comments for AddObject to tell users that delete the pointer they added is not allowed. This is almost enough.
Or, you could also make Object inherits from a base class which has a private destructor and a method named destroyByOwner.

Is value returned by std::unique_ptr::get valid after moving unique_ptr?

Consider the following code snippet:
class Owner {
public:
Owner(std::unique_ptr<int> ptr) : owned_pointer<int>(std:move(ptr)) {}
private:
std::unique_ptr<int> owned_pointer;
};
std::unique_ptr<int> ptr(new int);
int* ptr1 = ptr.get();
Owner new_owner(std::move(ptr));
Is it safe to assume that ptr1 is valid as long as new_owner stays in scope? It seems to work, but I can't find a specification that states that explicitly - is it undefined behavior/implementation specific and just happen to work for me, or the code posted above is valid (ptr1 is guaranteed to point to moved pointer as long as it stays alive)?
Yes, the C++11 specification guarantees that transferring ownership of an object from one unique_ptr to another unique_ptr does not change the location of the object itself, and that get() on the second unique_ptr returns the same as it would have on the first unique_ptr before the transfer.
Looking at N3337, section 20.7.1:
Additionally, u can, upon request, transfer ownership to another unique pointer u2. Upon completion of such a transfer, the following
postconditions hold:
u2.p is equal to the pre-transfer u.p,
u.p is equal to nullptr, and
if the pre-transfer u.d maintained state, such state has been transferred to u2.d.
where u is a unique_ptr object that stores a pointer u.p.
The first bullet answers the question directly, since get() is specified as returning the u.p.
Yes, it is valid.
You can have multiple (plain) pointers pointing to the same object. The question is how long those pointers are valid or when the object pointed to is deleted.
A unique_ptr stores one more plain pointer and takes ownership, meaning it is responsible for when the object is destroyed. Moving it to another unique_ptr just transfers ownership, the object itself is still the same and all plain pointers pointing to it remain valid.
Only when the ownership is not transferred (or released) and the owning unique_ptr is destroyed, it also destroys the object. This would be the moment where all plain pointers pointing to the object become dangling pointers and dereferencing them would be illegal.

Resources