I had a question about using unique-ptrs before. I get this answer recommending to use move-only objects. I defined a class as below:
class B {
const string objName;
public:
B ( B && ) = default;
B & operator= ( B && ) = default;
B ( const B & ) = delete;
B & operator= ( const B & ) = delete;
B(const string & name) :
objName(name) {
}
virtual ~B();
const string name() const { return objName;};
}
and I called B by this lines:
class A {
A(){}
void take(B b);
}
A a;
B b("test");
cout<<b.name();
a.take(std::move(b));
cout<<b.name();
My questions:
Yes, there is a point. Objects which manage resources (perhaps physical ones) that cannot/should not be shared between objects is the first example that comes to mind.
1) You wrote it incorrectly. Here is what I think you want based on this question and your previous one.
class B {
std::string objName;
public:
B ( B && ) = default;
B & operator= ( B && ) = default;
B ( const B & ) = delete;
B & operator= ( const B & ) = delete;
B(const std::string & name) :
objName(name) {}
virtual ~B() {}
std::string name() const { return objName;}
};
class A {
public:
std::vector<B> v;
void take(B && b)
{
v.push_back(std::move(b));
}
};
int main()
{
A a;
B b("test");
std::cout << "Before: " << b.name() << std::endl;
a.take(std::move(b));
std::cout << "After: " << b.name() << std::endl;
std::cout << "A has elements: " << std::endl;
for(B &b : a.v)
std::cout << " " << b.name() << std::endl;
}
2) You're accessing a value that has been moved-from, which doesn't make any sense! This answer already does a good job of explaining, but below I've also included text from a STL reference for std::move.
http://en.cppreference.com/w/cpp/utility/move
Unless otherwise specified, all standard library objects that have been moved from are placed in a valid but unspecified state. That is, only the functions without preconditions, such as the assignment operator, can be safely used on the object after it was moved from.
3) I have found two legitimate uses in my experience. In both cases the move-only objects controlled a physical resource which if shared by two objects would break everything.
About 3 : of course there is. I can think about many examples of objects that can be moved and not be copied, or shoudln't, anyway.
One example is a Socket class:
1) you want to give a default constructor for "empty" Socket which still didn't receive any IP or port.
2) you want give a constructor which gets an IP and port. upon construction the Socket will try to connect and may throw an exception if the connection fails
3) obvious thing is the destructor - it will disconnect the object and release any underlying-system resources that this object may hold
what about move constructor vs copy constructor?
let's say I have a function wich creates a socket and returns it. If I call the copy constructor that means that:
the new copied socket(return value) will try to connect to the same IP and port that the source socket was connected to. that may not be possible at all.
the source socket will be disconnected and destructed
it is quite possible that trying to copy the socket will just create a huge mess.
on the contrary, a move constructor solves this mass beutifully:
the return value receive all the underlying OS resources without disconnecting them or destroying them.
the source socket stays empty and the destructor has nothing to disconnect or destroy.
it appears that sockets would most likely to be only moved, not copied.
this could apply to a "Process" class - If I'll try to return a process by copying, I'd might try to open the same process again, only to shut down the original. a mess! by moving the process around I don't do it. I simply move the process around from function to function.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With