Does it make sense to define objects only for moving in C ++ 11?

I had a question about using unique-ptrs before. I get this answer , recommending using objects only for moving. I defined a class as shown 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 the following 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:

  • Even if I did not complete the move construct by default, I cannot write a.take (b), and I get a compilation of the error. I understand that the constrctor copy has been removed, but it seems like a logical choice is to use the move constructor when it defaults, without having to write std :: move like this. A.take (b)
  • As a result, the β€œtest” is printed twice. Why was object b not deleted after move was called? If the object b still exists, and a copy of it was sent to a.take (move (b)), then we do not have the use of relocation for rvalue objects.
  • Is it good practice to use objects only for movement, as described above (Removing the constructor and assignment operator, as well as the default movement constructor and the purpose of the movement)?
+7
c ++ pass-by-value c ++ 11 std smart-pointers
source share
2 answers

Yes, there is a point. Objects that manage resources (possibly physical) that cannot / should not be shared between objects are the first example that comes to mind.

1) You wrote it wrong. This is what I think you want based on this question and your previous one.

 class B { 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 : av) std::cout << " " << b.name() << std::endl; } 

2) You get access to the value that has been moved, and that makes no sense! This answer already explains well, but below I also included the text from the STL link for std :: move.

http://en.cppreference.com/w/cpp/utility/move

Unless otherwise specified, all standard library objects that have been moved from them are placed in a valid but unspecified state. That is, only functions without preconditions, such as assigning an operator, can be safely used on an object after moving it.

3) I found two legitimate uses in my experience. In both cases, objects only for movement controlled a physical resource, which, if it was divided by two objects, would break everything.

+5
source share

Around 3: of course there is. I can think of many examples of objects that can be moved, not copied, or shoudln't, anyway.

One example is the Socket class:
1) you want to provide a default constructor for an "empty" Socket, which so far has not received any IP address or port.
2) you want to give a constructor that receives an IP and port. when building, Socket will try to connect and may throw an exception if the connection does not work
3) the obvious thing is the destructor - it will disable the object and release any resources of the base system that this object may contain

how about move constructor vs copy constructor?
let's say I have a function that creates a socket and returns it. If I call the copy constructor, it means that:
the new copied socket (return value) will try to connect to the same IP and port to which the source was connected. it may not be possible at all.
the source socket will be disconnected and destroyed

it is possible that trying to copy a socket will just create a huge mess. on the contrary, the motion designer solves this mass:
the return value gets all the underlying OS resources, without shutting them down or without destroying them.
the source socket remains empty, and the destructor has nothing to disable or destroy.

it looks like sockets are more likely to be moved than copied.

this may be in the Process class. If I try to return the process by copying, I would try to open the same process again, only to close the original. mess! moving the process around, I do not. I just move the process from function to function.

+2
source share

All Articles