• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.
Sign in to follow this  
Followers 0
Ryan_001

C++ std::move() vs std::memcpy()

14 posts in this topic

I was working on a vector-like container, and while writing a resize() function came across an interesting question.

 

When moving an object between locations, when would std::move() not give the same results as simply a std::memcpy()?

 

There were only two situations that I could think of.  One was when the move constructor (or assignment operator) was intentionally used to do something strange (ie. not actually move).  The other that when using std::move() the src object could (in theory) be reused, or at the very least has to be destroyed, where-as with the std::memcpy() neither applies.

 

But in every other case I could think of (pointers, handles, reference counting) simply copying the bits should have the same result as calling std::move().?

1

Share this post


Link to post
Share on other sites

You might want to read the documentation of std::is_trivially_copyable.

 

I know the difference between POD and non-POD types.  Clearly when copying you can't just memcpy(), things like pointers, handles, COM interfaces, reference counting, ect... need to be updated.  

 

Closer to the topic is: http://en.cppreference.com/w/cpp/types/is_move_constructible.  Which has std::is_trivially_move_constructable.  Apart from throwing exceptions (which move is not supposed to do, much like destructors) what does calling std::move give you that std::memcpy() doesn't?

0

Share this post


Link to post
Share on other sites

Actually, my link does list all the important information. As the notes say:

Objects of trivially-copyable types are the only C++ objects that may be safely copied with std::memcpy or serialized to/from binary files with std::ofstream::write()/std::ifstream::read(). In general, a trivially copyable type is any type for which the underlying bytes can be copied to an array of char or unsigned char and into a new object of the same type, and the resulting object would have the same value as the original.

 

The properties listed above that cover the possible reasons you have already sliced into a bit in a formal way.

1

Share this post


Link to post
Share on other sites

Actually, my link does list all the important information. As the notes say:

 

 

Objects of trivially-copyable types are the only C++ objects that may be safely copied with std::memcpy or serialized to/from binary files with std::ofstream::write()/std::ifstream::read(). In general, a trivially copyable type is any type for which the underlying bytes can be copied to an array of char or unsigned char and into a new object of the same type, and the resulting object would have the same value as the original.

 

The properties listed above that cover the possible reasons you have already sliced into a bit in a formal way.

 

A) I'm talking about std::move() vs std::memcpy(), not copying.  What you've posted covers copies, not moves.

B) I want to know WHY is shouldn't be done.

1

Share this post


Link to post
Share on other sites
Are you talking in general, or concerning POD types only?

If in general, then you can't memcpy objects. If specifically POD, then they're likely equivalent.

[edit]i.e. You're not allowed to use memcpy on non-POD objects, so the question only applies to POD objects....
Assuming you're breaking the rules by memcpyijg non-POD objects, haven't you answered your own question -- any time that the move constructor does any real work (refcounting, swapping pointers, etc), then obviously this work won't be done by a memcpy.
1

Share this post


Link to post
Share on other sites


If specifically POD, then they're likely equivalent.

 

in pod land, as i recall, copy is a straight copy, and move is used for overlapping memory addresses (IE uses an intermediate buffer of some sort). since i never deal with overlapping addresses, i only use memcpy and then really only via ZeroMemory()

.  

0

Share this post


Link to post
Share on other sites

Clearly I'm not being clear.

 

I understand what a POD type is, and what it allows you to do.  I'm not talking about copying.  No copies.  Forget copying.  I'm only talking about move here.  I also understand what a copy constructor is, what a move constructor is, and why you would use one over another.

 

What I want to know is: under what circumstances would using std::memcpy() not yield the same results as std::move()?  Again, NOT copy, but move.  The ones that I can thinks of are:

 

1) std::move() throws an exception (either through the move constructor or the move assignment operator, whichever one you're using), which is generally considered bad, like destructor throwing bad.

2) in the case of hardware mapped memory, like an object place-constructed in a particular segment of memory by the OS

3) where a move constructor (or assignment operator) is intentionally deleted or not accessible, but again this kinda leads back into the original question, cause I can't think of any situation where copy would be allowed but moving disabled apart from 2

4) where the src object of a move has to (or can be) re-used

 

I understand that std::move(), std::memcpy(), and normal copying all copy bytes around.  But in the context of C++ a move is different than a copy.  So yes I am talking about std::memcpy(), but I'm talking about move semantics not copy semantics.  POD types and std::is_trivially_copyable refer to copy semantics.  For example a class like:

struct Object { 
   char* data; 
   Object () : data(new char[10]);
   virtual ~Object () { delete[] data; }
   };

is not trivially copyable (you'd have two objects pointing to the same data on the heap), but... is it trivially moveable?  There are no exceptions thrown.  The pointer will move properly with a std::memcpy(), as there will be still only one owner.  As long as the src isn't destructed we don't have a data leak.  Does the hidden v-table pointer get copied properly?  Will something else get mangled?

 

I hope that makes my question clearer.

1

Share this post


Link to post
Share on other sites

One situation where memcpy() won't work but std::move() will is when the object's constructors and destructor handle self-registration. For example, if it registers itself as part of the root set to a garbage collector by giving the garbage collector it's address. If you just copy the the memory without updating the root set for the GC, the GC will be trying to use the old memory location for its sweeps.

Didn't think of that one, thank-you.
 

In adition to SiCrane's example, another thing that could complicate moving is pointers into the object itself. For example, a small vector might have a pointer that points within the object when there are few members, and to allocated memory when there are lots. That pointer would need to be updated to point within the moved object.

Another good point.
0

Share this post


Link to post
Share on other sites

I'm not sure if someone mentioned this, but a clear difference when your class allocates memory is that std::memcpy will not remove ownership from the original. So when your object dies, it will release the memory, but the object you copied will still hold a pointer to the released memory, causing a crash down the road. std::move, on the other hand, will release ownership from the original object (zeroing pointers, etc) so that it can be destroyed without affecting the state of the target object.

 

A move affects both the source and the destination, while a copy only affects the destination.

1

Share this post


Link to post
Share on other sites

I'm not sure if someone mentioned this, but a clear difference when your class allocates memory is that std::memcpy will not remove ownership from the original. So when your object dies, it will release the memory, but the object you copied will still hold a pointer to the released memory, causing a crash down the road. std::move, on the other hand, will release ownership from the original object (zeroing pointers, etc) so that it can be destroyed without affecting the state of the target object.

 

A move affects both the source and the destination, while a copy only affects the destination.

 

Exactly.

 

 


struct Object {
char* data;
Object () : data(new char[10]);
virtual ~Object () { delete[] data; }
};
is not trivially copyable (you'd have two objects pointing to the same data on the heap), but... is it trivially moveable?  There are no exceptions thrown.  The pointer will move properly with a std::memcpy(), as there will be still only one owner.  As long as the src isn't destructed we don't have a data leak.  Does the hidden v-table pointer get copied properly?  Will something else get mangled?

 

The pointer will NOT move properly. It gets copied properly. There are now 2 owners, not 1. You said "as long as src isn't destructed" but that's an important detail that highlights a major difference between memcpy and move.

Edited by achild
1

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0