Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Okay to move an object?

Reply
Thread Tools

Okay to move an object?

 
 
Frederick Gotham
Guest
Posts: n/a
 
      06-26-2006

(Before I begin, please don't suggest to me to use "std::vector" rather
than actual arrays.)

I understand that an object can have resources (e.g. dynamically
allocated memory), and so we have to copy an object properly via copy-
construction rather than using memcpy.

However, is it okay to move an object manually (i.e. by using memcpy or
memmove)?

I have an algorithm for rotating an array. It turns:

A B C D E F G

into:

B C D E F G A

and if run a second time, that would become:

C D E F G A B


I intend for it to be used on anything from and array of char's, to an
array of vector's.

Is there anything wrong with the way it moves objects around?

Here's some sample code:


#include <iostream>
using std::cout;

#include <cstdlib>
using std::memcpy;

#include <cstring>
using std::memmove;


template<class T>
void RotateArrayOnce( T * const p_start, T * const p_over )
{
unsigned long const len = p_over - p_start;

unsigned char * const p_temp_storage = new unsigned char[ sizeof(T)
];

memcpy( p_temp_storage, p_start, sizeof(T) );

memmove( p_start, p_start + 1, sizeof(T) * (len - 1) );

memmove( p_over - 1, p_temp_storage, sizeof(T) );

delete [] p_temp_storage;
}

int main()
{
char buffer[] = "ABCDE";

cout << buffer << '\n';

RotateArrayOnce(buffer, *(&buffer + 1) - 1 );

cout << buffer << '\n';

RotateArrayOnce(buffer, *(&buffer + 1) - 1 );

cout << buffer << '\n';

std::system("PAUSE");
}


At first thought, I don't see how it could be a problem to simply move an
object in memory (assuming the target location is suitably aligned).

Only thing I can see which could make things go awry is if the object
kept its own address stored within it for some reason.


--

Frederick Gotham
 
Reply With Quote
 
 
 
 
Phlip
Guest
Posts: n/a
 
      06-27-2006
Frederick Gotham wrote:

> (Before I begin, please don't suggest to me to use "std::vector" rather
> than actual arrays.)


std::vector _are_ actual arrays.

> However, is it okay to move an object manually (i.e. by using memcpy or
> memmove)?


That is, indirectly, a FAQ.

http://www.parashift.com/c++-faq-lit....html#faq-26.7
"What is a 'POD type'?"

> I intend for it to be used on anything from and array of char's, to an
> array of vector's.


Are vectors PODs?

> using std::memcpy;


You might try some member of the std::copy() family. They are templated, so
they will drill down to your actual type and invoke its copy operations.

If you stick with memcpy, you are performing the equivalent of
reinterpret_cast<char *>(&element) on each element. 'reinterpret_cast<>' is
bad, and should be avoided, including all similar situations that secretly
throw away type information.

And you have not yet made any case for not using std::vector, besides you
have stuck with functions that you understand. Don't reinvent wheels while
on the clock!

--
Phlip
http://c2.com/cgi/wiki?ZeekLand <-- NOT a blog!!!


 
Reply With Quote
 
 
 
 
Victor Bazarov
Guest
Posts: n/a
 
      06-27-2006
Frederick Gotham wrote:
> (Before I begin, please don't suggest to me to use "std::vector"
> rather than actual arrays.)
>
> I understand that an object can have resources (e.g. dynamically
> allocated memory), and so we have to copy an object properly via copy-
> construction rather than using memcpy.
>
> However, is it okay to move an object manually (i.e. by using memcpy
> or memmove)?


Huh? If you understand that we "have to copy an object properly",
why ask if it's OK to do it improperly?

>
> I have an algorithm for rotating an array. It turns:
>
> A B C D E F G
>
> into:
>
> B C D E F G A
>
> and if run a second time, that would become:
>
> C D E F G A B
>
>
> I intend for it to be used on anything from and array of char's, to an
> array of vector's.
>
> Is there anything wrong with the way it moves objects around?


Yes. Unless your objects are of a POD type, using 'memcpy' or 'memmove'
on them is *undefined*. Usually it means that it's impossible to define
the consequences of that action without imposing too many limitations on
the language implementations.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask


 
Reply With Quote
 
Daniel T.
Guest
Posts: n/a
 
      06-27-2006
In article <fw_ng.10625$(E-Mail Removed)>,
Frederick Gotham <(E-Mail Removed)> wrote:

> (Before I begin, please don't suggest to me to use "std::vector" rather
> than actual arrays.)


Why? Would it be OK to suggest a method of accomplishing what you want
to accomplish?

template < typename FwIt >
void RotateArrayOnce( FwIt begin, FwIt end ) {
std::rotate( begin, begin + 1, end );
}

Unless you are doing a homework assignment, you are wasting your time.

If you *are* doing a homework assignment, the what you need to do is
walk the first element of the array down using std::swap.
 
Reply With Quote
 
Kaz Kylheku
Guest
Posts: n/a
 
      06-27-2006
Frederick Gotham wrote:
> (Before I begin, please don't suggest to me to use "std::vector" rather
> than actual arrays.)
>
> I understand that an object can have resources (e.g. dynamically
> allocated memory), and so we have to copy an object properly via copy-
> construction rather than using memcpy.
>
> However, is it okay to move an object manually (i.e. by using memcpy or
> memmove)?


Not in general, because objects may be entangled in relationships which
are hinged on their address.

An object may contain pointers to parts of itself. For instance, an
object representing a buffered I/O stream over a file might contain a
buffer, as well as a pointer to the current read position within the
buffer rather than an index. If you copy the object, its pointer still
points within the original object.

There may be other objects which know about that object, and refer to
it by its address. For instance, a node in a binary tree has a parent
which points to it via a child pointer. A naive copy of the object will
retain that parent, but that parent still points to the original object
as its child. Treating this node as the root of a subtree could wreck
the original tree, depending on what kind of operation is attempted.

C++ polymorphic objects may have this kind of information in them, as a
way of implementing the object system. For instance, the derived part
of an object could have a hidden back-pointer to a base class part or
vice versa. So you cannot treat these types of objects as raw memory to
be copied around.

Even plain C-like structures cannot necessarily be treated that way.
Although the C++ implementation may allow a bit copy, whether or not
that makes sense still depends on the meaning of that data type and how
it relates to other data.

For instance FILE streams in the Standard C library are not C++
classes, but it's still forbidden to copy them.

Another example is the va_list type, which can only be copied by
va_copy, not by assignment.

> Only thing I can see which could make things go awry is if the object
> kept its own address stored within it for some reason.


Or if that object is part of a larger data structure which knows about
that object's address!

Imagine if you populated the array with the nodes of a binary tree and
ran your sorting algorithm. It would scramble the link pointers within
that tree, destroying the whole thing.

You'd have to run some kind of "tree repair" afterward to rebuild the
structure. But then your sorting algorithm would no longer be generic:
it would work specifically with objects which may be bitwise copied
/provided/ that a special fixup is invoked afterward.

C++ doesn't provide any standard way to fix up the internal information
of class objects which may have such information (i.e. other than
"plain old datatypes").

 
Reply With Quote
 
Frederick Gotham
Guest
Posts: n/a
 
      06-27-2006
Kaz Kylheku posted:

> Frederick Gotham wrote:
>>
>> However, is it okay to move an object manually (i.e. by using memcpy

or
>> memmove)?

>
> Not in general, because objects may be entangled in relationships which
> are hinged on their address.



The reply I was waiting for.


> An object may contain pointers to parts of itself. For instance, an
> object representing a buffered I/O stream over a file might contain a
> buffer, as well as a pointer to the current read position within the
> buffer rather than an index. If you copy the object, its pointer still
> points within the original object.



While I had fathomed that this was possible, I was unsure as to whether
it was "acceptable".

Are you saying that it is indeed acceptable for an object to store its
own address within itself (or the address of a member object, or base
class object)? If so, I'll have to take this into account when moving the
object's bytes to another location in memory.


> There may be other objects which know about that object, and refer to
> it by its address.



When the "RotateArrayOnce" function is invoked, I can assume that nothing
will be depending upon its original address. (It's the programmer's
responsibility to ensure this before invoking my reusable code).

After all, the programmer would not re-arrange an array if the addresses
of the array's elements were of significance.


> For instance, a node in a binary tree has a parent
> which points to it via a child pointer. A naive copy of the object will
> retain that parent, but that parent still points to the original object
> as its child. Treating this node as the root of a subtree could wreck
> the original tree, depending on what kind of operation is attempted.



Again, the programmer must ensure that they are "allowed" to re-arrange
the objects.


> C++ polymorphic objects may have this kind of information in them, as a
> way of implementing the object system. For instance, the derived part
> of an object could have a hidden back-pointer to a base class part or
> vice versa. So you cannot treat these types of objects as raw memory to
> be copied around.



I see. (Again we're back to an object storing its own address within
itself).


> Even plain C-like structures cannot necessarily be treated that way.



Why is that? Is it because it's also acceptable for a C-like structure to
store its own address within itself?


> Although the C++ implementation may allow a bit copy, whether or not
> that makes sense still depends on the meaning of that data type and how
> it relates to other data.



I see. (Again, self-addressing).


> For instance FILE streams in the Standard C library are not C++
> classes, but it's still forbidden to copy them.
>
> Another example is the va_list type, which can only be copied by
> va_copy, not by assignment.



Yes... but I'm not real copying an object; all I'm doing is moving it.
I'll try to explain:

Whereas the object's bytes may have existed at address 0x00000012, it now
exists at address 0x00000008.

If I were to attempt, subsequent to the copy, to access the data at the
original address of 0x00000012, THEN I'd have a problem... but I do not
do this -- I choose to discard the data at the original address.

The net effect is a simple move of data in memory, nothing more.

(It actually reminds me of the old-fashioned way of moving a file:
You copy it, then delete the original.
Even if it's forbidden to have more than one copy of the file, it doesn't
matter... because I destroy the original immediately, ensuring that the
original is never accessed subsequent to being copied.)


>> Only thing I can see which could make things go awry is if the object
>> kept its own address stored within it for some reason.

>
> Or if that object is part of a larger data structure which knows about
> that object's address!



Again, I don't need to worry about this, because the programmer must
supply the function with an array which is "re-arrangeable".

Thank you very much Kaz for your help.

So this brings me on to my next question:


How do I (legitimately) move an object in memory?


Some people have suggested that I use "std::swap", but then I'd need to
have another object to swap it with... but that's not what I want -- I
simply want to move it into another raw memory location, without the need
for a guinea pig to swap it with.

Maybe a Standard library function like:

template<class T>
void MoveObjectInMemory( T &obj, unsigned char *p_destination );


--

Frederick Gotham
 
Reply With Quote
 
wij@seed.net.tw
Guest
Posts: n/a
 
      06-27-2006
Frederick Gotham wrote:

> (Before I begin, please don't suggest to me to use "std::vector" rather
> than actual arrays.)
>
> I understand that an object can have resources (e.g. dynamically
> allocated memory), and so we have to copy an object properly via copy-
> construction rather than using memcpy.
>
> However, is it okay to move an object manually (i.e. by using memcpy or
> memmove)?
>
> ...


The discussions might help.
http://groups.google.com.tw/group/co...4c8b920c0521f3


IJ. Wang

 
Reply With Quote
 
Jim Langston
Guest
Posts: n/a
 
      06-27-2006
"Frederick Gotham" <(E-Mail Removed)> wrote in message
news:fw_ng.10625$(E-Mail Removed)...
>
> (Before I begin, please don't suggest to me to use "std::vector" rather
> than actual arrays.)
>
> I understand that an object can have resources (e.g. dynamically
> allocated memory), and so we have to copy an object properly via copy-
> construction rather than using memcpy.
>
> However, is it okay to move an object manually (i.e. by using memcpy or
> memmove)?
>
> I have an algorithm for rotating an array. It turns:
>
> A B C D E F G
>
> into:
>
> B C D E F G A
>
> and if run a second time, that would become:
>
> C D E F G A B
>
>
> I intend for it to be used on anything from and array of char's, to an
> array of vector's.
>
> Is there anything wrong with the way it moves objects around?
>
> Here's some sample code:
>
>
> #include <iostream>
> using std::cout;
>
> #include <cstdlib>
> using std::memcpy;
>
> #include <cstring>
> using std::memmove;
>
>
> template<class T>
> void RotateArrayOnce( T * const p_start, T * const p_over )
> {
> unsigned long const len = p_over - p_start;
>
> unsigned char * const p_temp_storage = new unsigned char[ sizeof(T)
> ];
>
> memcpy( p_temp_storage, p_start, sizeof(T) );
>
> memmove( p_start, p_start + 1, sizeof(T) * (len - 1) );
>
> memmove( p_over - 1, p_temp_storage, sizeof(T) );
>
> delete [] p_temp_storage;
> }
>
> int main()
> {
> char buffer[] = "ABCDE";
>
> cout << buffer << '\n';
>
> RotateArrayOnce(buffer, *(&buffer + 1) - 1 );
>
> cout << buffer << '\n';
>
> RotateArrayOnce(buffer, *(&buffer + 1) - 1 );
>
> cout << buffer << '\n';
>
> std::system("PAUSE");
> }
>
>
> At first thought, I don't see how it could be a problem to simply move an
> object in memory (assuming the target location is suitably aligned).
>
> Only thing I can see which could make things go awry is if the object
> kept its own address stored within it for some reason.


Consider a class that stores a pointer into a buffer. It creates a char
array either dynamically or statically, then stores a pointer at the current
position. To copy this class it would need a copy constructor, and would
also need an assigment operator for some uses.

Typically, you can not memcpy any object that has or needs a custom copy or
assigment operator. Look up the "rule of three", sorry, don't have a link
but it's in the FAQ.

memcpy should work for any POD (Plain old data) because POD does not need or
have custom copy and assigment operators. The correct way to do it would be
to invoke the classes copy operator.


 
Reply With Quote
 
Daniel T.
Guest
Posts: n/a
 
      06-27-2006
In article <Z30og.10626$(E-Mail Removed)>,
Frederick Gotham <(E-Mail Removed)> wrote:

> > For instance FILE streams in the Standard C library are not C++
> > classes, but it's still forbidden to copy them.
> >
> > Another example is the va_list type, which can only be copied by
> > va_copy, not by assignment.

>
>
> Yes... but I'm not real copying an object; all I'm doing is moving it.
> I'll try to explain:
>
> Whereas the object's bytes may have existed at address 0x00000012, it now
> exists at address 0x00000008.
>
> If I were to attempt, subsequent to the copy, to access the data at the
> original address of 0x00000012, THEN I'd have a problem... but I do not
> do this -- I choose to discard the data at the original address.
>
> The net effect is a simple move of data in memory, nothing more.
>
> (It actually reminds me of the old-fashioned way of moving a file:
> You copy it, then delete the original.
> Even if it's forbidden to have more than one copy of the file, it doesn't
> matter... because I destroy the original immediately, ensuring that the
> original is never accessed subsequent to being copied.)
>
>
> >> Only thing I can see which could make things go awry is if the object
> >> kept its own address stored within it for some reason.

> >
> > Or if that object is part of a larger data structure which knows about
> > that object's address!

>
>
> Again, I don't need to worry about this, because the programmer must
> supply the function with an array which is "re-arrangeable".
>
> Thank you very much Kaz for your help.
>
> So this brings me on to my next question:
>
>
> How do I (legitimately) move an object in memory?
>
>
> Some people have suggested that I use "std::swap", but then I'd need to
> have another object to swap it with... but that's not what I want -- I
> simply want to move it into another raw memory location, without the need
> for a guinea pig to swap it with.
>
> Maybe a Standard library function like:
>
> template<class T>
> void MoveObjectInMemory( T &obj, unsigned char *p_destination );
>


Suddenly the requirements change. Before you wanted to swap objects now
you want to move an object to some specific memory location. Your design
is deeply flawed, but it can be done. Placement new and the copy
constructor is the way to go in this case.
 
Reply With Quote
 
Jerry Coffin
Guest
Posts: n/a
 
      06-27-2006
In article <(E-Mail Removed)>,
http://www.velocityreviews.com/forums/(E-Mail Removed) says...

[ ... ]

> Suddenly the requirements change. Before you wanted to swap objects now
> you want to move an object to some specific memory location. Your design
> is deeply flawed, but it can be done. Placement new and the copy
> constructor is the way to go in this case.


I have to (for once) agree with Daniel: it sounds like your design is
deeply flawed. How about if we go back to somewhere close to the
beginning, and you tell us what you're really trying to accomplish
here? It seems to me that we're putting the cart before the horse,
trying to figure out how to do things before we figure out what
should really be done in the first place.

--
Later,
Jerry.

The universe is a figment of its own imagination.
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Writing move constructors and move assignment Andrew Tomazos C++ 2 12-12-2011 01:45 PM
Okay to move an "object" will-nilly? Frederick Gotham C Programming 33 07-11-2006 11:19 PM
I am trying to move spaces to a weblistbox and when I move them... Eduardo78 ASP .Net Web Controls 0 11-03-2005 06:06 PM
Okay to Auction? Tony S Cisco 2 04-16-2005 06:02 PM
Re: ViewState + AutoIncrement -- Okay; Session + AutoIncrement -- Not okay Gene Gorokhovsky ASP .Net 0 07-17-2003 02:48 PM



Advertisments