By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
446,406 Members | 954 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 446,406 IT Pros & Developers. It's quick & easy.

Array copying technique

P: n/a
Below you will find some code I wrote to see if I could wrap array copying
(especially for multi-dimensional arrays) in a simple class and/or
function. It seems to work fine for one-dimensioned arrays as well as
two-dimensioned ones. I am sure three- or more-dimensioned array are just
as OK here.

My concern was that I couldn't use 'std::copy' to copy multi-dimensional
arrays. Perhaps in the future we'll see specialisations of 'std::copy'
function that will work with multidimensional arrays similarly to the
'arrcpy' function. [I intentionally named 'arrcpy' that way to indicate
that the arguments are similar to 'strcpy', first the destination, then
the source.]

I've not managed to make this code accept a constant array (or array of
const T), simply because it would probably require a cast for one of the
placement new operators. But in most cases it doesn't matter. Extend it
if you need to.

I am putting it here because I think you might want to comment on it. If
you think you could use it, use it. If you think you have seen something
like this before, do mention it. I am not claiming any innovation here,
just my laziness to look for something similar that has been already done.

Regards,

Victor

cut here 8<-------------------------------------------------- >8 cut here

#include <memory> // for placement new

template<class T, size_t N> struct AC
{
struct W
{
T arr[N];
};

AC(T (*ar1)[N], T (*ar2)[N]) : w1(new (ar1) W), w2(new (ar2) W) {}
~AC() { *w1 = *w2; }

W *w1, *w2;
};

template<class T, size_t N> void arrcpy(T (&ar1)[N], T (&ar2)[N])
{
AC<T,N> ac(&ar1, &ar2);
}

int main()
{
int ai[1000] = { 1,2,3 };
int bi[1000] = { 5,6,7 };
double a[100][10] = { 1,2,3 };
double b[100][10] = { 5,6,7 };

arrcpy(ai, bi);
arrcpy(a, b);

return 0;
}

cut here 8<-------------------------------------------------- >8 cut here
Dec 12 '05 #1
Share this Question
Share on Google+
5 Replies


P: n/a
On Mon, 12 Dec 2005 14:28:42 -0500, Victor Bazarov
<v.********@comAcast.net> wrote:
Below you will find some code I wrote to see if I could wrap array copying [...]I am putting it here because I think you might want to comment on it. cut here 8<-------------------------------------------------- >8 cut here

#include <memory> // for placement new

template<class T, size_t N> struct AC
{
struct W
{
T arr[N];
};

AC(T (*ar1)[N], T (*ar2)[N]) : w1(new (ar1) W), w2(new (ar2) W) {} this should probably be:
AC(T (*ar1)[N], T (*ar2)[N]) : w1 (reinterpret_cast<W*>
ar1)),w2(reinterpret_cast<W*> (ar2)) {}
~AC() { *w1 = *w2; }

W *w1, *w2;
};

template<class T, size_t N> void arrcpy(T (&ar1)[N], T (&ar2)[N])
{
AC<T,N> ac(&ar1, &ar2);
}


Otherwise it should work.

Best regards,
Roland Pibinger

Dec 13 '05 #2

P: n/a
Roland Pibinger wrote:
On Mon, 12 Dec 2005 14:28:42 -0500, Victor Bazarov
<v.********@comAcast.net> wrote:

Below you will find some code I wrote to see if I could wrap array copying


[...]
I am putting it here because I think you might want to comment on it.


cut here 8<-------------------------------------------------- >8 cut here

#include <memory> // for placement new

template<class T, size_t N> struct AC
{
struct W
{
T arr[N];
};

AC(T (*ar1)[N], T (*ar2)[N]) : w1(new (ar1) W), w2(new (ar2) W) {}


this should probably be:
AC(T (*ar1)[N], T (*ar2)[N]) : w1 (reinterpret_cast<W*>
ar1)),w2(reinterpret_cast<W*> (ar2)) {}

~AC() { *w1 = *w2; }

W *w1, *w2;
};

template<class T, size_t N> void arrcpy(T (&ar1)[N], T (&ar2)[N])
{
AC<T,N> ac(&ar1, &ar2);
}

Otherwise it should work.


Thanks, Roland. What do you think is the advantage of using the
reinterpret_cast over using placement new?

BTW, I found where it would not work very well (I am sure that some kind
of compile time assertion should help catch those):

if sizeof(W) != sizeof(arr)

IOW, if to create a struct W some padding is required, copying structs
will cause memory overrun, undefined behaviour.

V
Dec 13 '05 #3

P: n/a
On Tue, 13 Dec 2005 17:01:11 -0500, Victor Bazarov
<v.********@comAcast.net> wrote:
Roland Pibinger wrote:
On Mon, 12 Dec 2005 14:28:42 -0500, Victor Bazarov
AC(T (*ar1)[N], T (*ar2)[N]) : w1(new (ar1) W), w2(new (ar2) W) {}
this should probably be:
AC(T (*ar1)[N], T (*ar2)[N]) : w1 (reinterpret_cast<W*>
ar1)),w2(reinterpret_cast<W*> (ar2)) {}


Thanks, Roland. What do you think is the advantage of using the
reinterpret_cast over using placement new?


You actually perform a reinterpret_cast with placement new :-), it's
even less safe than reinterpret_cast. You can cast any type to any
other type in C and C++ (not that I recommend that). Why not use the
'idiomatic' approach?
BTW, I found where it would not work very well (I am sure that some kind
of compile time assertion should help catch those):

if sizeof(W) != sizeof(arr)

IOW, if to create a struct W some padding is required, copying structs
will cause memory overrun, undefined behaviour.


Yes, in theory. Padding can only occur at the end in this case. Are
compilers allowed to padd at the end of a struct?

Best wishes,
Roland Pibinger

Dec 13 '05 #4

P: n/a

"Roland Pibinger" <rp*****@yahoo.com> wrote in message
news:43**************@news.utanet.at...
On Tue, 13 Dec 2005 17:01:11 -0500, Victor Bazarov
<v.********@comAcast.net> wrote:

BTW, I found where it would not work very well (I am sure that some kind
of compile time assertion should help catch those):

if sizeof(W) != sizeof(arr)

IOW, if to create a struct W some padding is required, copying structs
will cause memory overrun, undefined behaviour.


Yes, in theory. Padding can only occur at the end in this case. Are
compilers allowed to padd at the end of a struct?


Yes, padding is allowed after any struct member (but not before the first).

For some implementations this behavior is configurable (e.g. with
a #pragma).

-Mike
Dec 13 '05 #5

P: n/a
Roland Pibinger wrote:
On Tue, 13 Dec 2005 17:01:11 -0500, Victor Bazarov
<v.********@comAcast.net> wrote:

Roland Pibinger wrote:
On Mon, 12 Dec 2005 14:28:42 -0500, Victor Bazarov

AC(T (*ar1)[N], T (*ar2)[N]) : w1(new (ar1) W), w2(new (ar2) W) {}

this should probably be:
AC(T (*ar1)[N], T (*ar2)[N]) : w1 (reinterpret_cast<W*>
ar1)),w2(reinterpret_cast<W*> (ar2)) {}
Thanks, Roland. What do you think is the advantage of using the
reinterpret_cast over using placement new?

You actually perform a reinterpret_cast with placement new :-), it's
even less safe than reinterpret_cast.


Could you please elaborate on safety, since you've mentioned it? Thanks!
You can cast any type to any
other type in C and C++ (not that I recommend that). Why not use the
'idiomatic' approach?


Why would 'reinterpret_cast' be more idiomatic than 'placement new'?
I try to always follow the rule: when constructing an object, even if it
is a POD object, use 'new' unless there is a compelling reason not to.
So, if functionally they are equivalent, I don't see the reason to prefer
the cast.
BTW, I found where it would not work very well (I am sure that some kind
of compile time assertion should help catch those):

if sizeof(W) != sizeof(arr)

IOW, if to create a struct W some padding is required, copying structs
will cause memory overrun, undefined behaviour.

Yes, in theory. Padding can only occur at the end in this case. Are
compilers allowed to padd at the end of a struct?


What's so special about the end? 5.3.3 speaks about any padding needed
for placing objects of that type in an array, so if there are special
alignment requirements for a struct (can there be?), then we may end up
with some additional space between objects (added after the end of 'arr'
member)...

V
Dec 13 '05 #6

This discussion thread is closed

Replies have been disabled for this discussion.