Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   C++ (http://www.velocityreviews.com/forums/f39-c.html)
-   -   Array inside struct inside container (http://www.velocityreviews.com/forums/t752907-array-inside-struct-inside-container.html)

none 08-16-2011 07:12 PM

Array inside struct inside container
 
I've seen forum posts here and there asking "How do I create an STL
container of arrays?" Or, equivalently, "How do I fix this syntax:"

std::vector<float[20]> v;

The answers to these questions are generally one of two things:

1) Use a boost::array, or
2) Put the array in a struct, like so:

// In header file
stuct wrapper { float f[20]; };

// In CPP file
std::vector<wrapper> v;

I was under the impression that things stored in STL containers needed to
be copyable and assignable. That second option seems incorrect to me,
unless the compiler is expected to generate both an operator= and a copy
constructor for the struct that perform a memcpy() for the contents of f.

Is it?

Victor Bazarov 08-16-2011 07:28 PM

Re: Array inside struct inside container
 
On 8/16/2011 3:12 PM, none wrote:
> I've seen forum posts here and there asking "How do I create an STL
> container of arrays?" Or, equivalently, "How do I fix this syntax:"
>
> std::vector<float[20]> v;
>
> The answers to these questions are generally one of two things:
>
> 1) Use a boost::array, or
> 2) Put the array in a struct, like so:
>
> // In header file
> stuct wrapper { float f[20]; };
>
> // In CPP file
> std::vector<wrapper> v;
>
> I was under the impression that things stored in STL containers needed to
> be copyable and assignable. That second option seems incorrect to me,
> unless the compiler is expected to generate both an operator= and a copy
> constructor for the struct that perform a memcpy() for the contents of f.


Not memcpy. See below.

> Is it?


A struct with an array as a data member is assignable. The default
compiler-provided assignment operator performs memberwise assignment
that for array members means element-wise assignment. You can verify it
by compiling/running this test program:

#include <iostream>

struct A {
A& operator=(A const&) { std::cout << "A::op=\n"; return *this; }
};
struct B { A aa[10]; };

int main() {
B b1, b2;
b1 = b2;
}

V
--
I do not respond to top-posted replies, please don't ask

none 08-16-2011 08:07 PM

Re: Array inside struct inside container
 
Victor Bazarov wrote:

> A struct with an array as a data member is assignable. The default
> compiler-provided assignment operator performs memberwise assignment
> that for array members means element-wise assignment.



Thanks! I was uninformed. I've been using wrapper classes in my
ignorance, which do perform a memcpy(). This means that I could get rid of
them, but based on your example, I think the memcpy() might be slightly
faster. It's a micro-optimization, I know, but it looks like the compiler
inserts something like a for-loop that invokes operator= for each element,
where memcpy() is probably optimized down to basically a single REP-MOV
instruction on x86. Or, maybe I'm just emotionally attached to my wrapper
classes now and want to continue using them.

Alain Ketterlin 08-16-2011 09:26 PM

Re: Array inside struct inside container
 
none <none@none.none> writes:

> Victor Bazarov wrote:
>
>> A struct with an array as a data member is assignable. The default
>> compiler-provided assignment operator performs memberwise assignment
>> that for array members means element-wise assignment.

>
> Thanks! I was uninformed. I've been using wrapper classes in my
> ignorance, which do perform a memcpy(). This means that I could get rid of
> them, but based on your example, I think the memcpy() might be slightly
> faster. It's a micro-optimization, I know, but it looks like the compiler
> inserts something like a for-loop that invokes operator= for each element,
> where memcpy() is probably optimized down to basically a single REP-MOV
> instruction on x86.


You should better leave that optim to the compiler (it probably does it
already for pod types). And your code will also "do the right thing"
when operator= on array elements does non-trivial things, i.e., on
non-pod types.

-- Alain.

Bo Persson 08-17-2011 10:29 AM

Re: Array inside struct inside container
 
none wrote:
> Victor Bazarov wrote:
>
>> A struct with an array as a data member is assignable. The default
>> compiler-provided assignment operator performs memberwise
>> assignment that for array members means element-wise assignment.

>
>
> Thanks! I was uninformed. I've been using wrapper classes in my
> ignorance, which do perform a memcpy(). This means that I could
> get rid of them, but based on your example, I think the memcpy()
> might be slightly faster. It's a micro-optimization, I know, but
> it looks like the compiler inserts something like a for-loop that
> invokes operator= for each element, where memcpy() is probably
> optimized down to basically a single REP-MOV instruction on x86.
> Or, maybe I'm just emotionally attached to my wrapper classes now
> and want to continue using them.


The compiler can easily optimize the memberwise copy into a memcpy()
whenever that is possible (and deemed "slighly faster").

It is an old myth that memcpy() is always the fastest. Smart compilers
can do a lot of things that is sometimes ever better (like taking
advantage of known alignment and size).



Bo Persson



Juha Nieminen 08-17-2011 01:06 PM

Re: Array inside struct inside container
 
Bo Persson <bop@gmb.dk> wrote:
> The compiler can easily optimize the memberwise copy into a memcpy()
> whenever that is possible (and deemed "slighly faster").
>
> It is an old myth that memcpy() is always the fastest. Smart compilers
> can do a lot of things that is sometimes ever better (like taking
> advantage of known alignment and size).


Another important aspect is that if the elements happen to be class
instances, memcpy() could potentially break it badly. It's just better
to let the compiler do the copying unless there's a good reason not to.

none 08-22-2011 01:20 PM

Re: Array inside struct inside container
 
In article <Xns9F43865A8800Dnonenonenone@69.16.186.52>,
none <none@none.none> wrote:
>I've seen forum posts here and there asking "How do I create an STL
>container of arrays?" Or, equivalently, "How do I fix this syntax:"
>
> std::vector<float[20]> v;


The obvious answer is:

std::vector< std::vector<float> > v;

>The answers to these questions are generally one of two things:
>
>1) Use a boost::array, or
>2) Put the array in a struct, like so:
>
> // In header file
> stuct wrapper { float f[20]; };
>
> // In CPP file
> std::vector<wrapper> v;
>
>I was under the impression that things stored in STL containers needed to
>be copyable and assignable. That second option seems incorrect to me,
>unless the compiler is expected to generate both an operator= and a copy
>constructor for the struct that perform a memcpy() for the contents of f.
>
>Is it?




James Kanze 08-22-2011 06:01 PM

Re: Array inside struct inside container
 
On Aug 16, 9:18 pm, Leigh Johnston <le...@i42.co.uk> wrote:
> On 16/08/2011 21:07, none wrote:


> > Victor Bazarov wrote:


> >> A struct with an array as a data member is assignable. The default
> >> compiler-provided assignment operator performs memberwise assignment
> >> that for array members means element-wise assignment.


> > Thanks! I was uninformed. I've been using wrapper classes in my
> > ignorance, which do perform a memcpy(). This means that I could get rid of
> > them, but based on your example, I think the memcpy() might be slightly
> > faster. It's a micro-optimization, I know, but it looks like the compiler
> > inserts something like a for-loop that invokes operator= for each element,
> > where memcpy() is probably optimized down to basically a single REP-MOV
> > instruction on x86. Or, maybe I'm just emotionally attached to my wrapper
> > classes now and want to continue using them.


> Your opimization is indeed premature: VC++, for example, will emit a REP
> MOVS instruction when copying member arrays of builtin types.


Even today? I seem to recall reading somewhere (of unknown
reliability, so it could easily be wrong) that on a modern
machine, REP MOVS was less efficient than a loop using more
classical instructions.

Anyway, as Bo has pointed out, the compiler can take advantage
of known alignment, etc., and can certainly generate faster code
than would result from calling memcpy.

--
James Kanze

none 08-23-2011 09:20 AM

Re: Array inside struct inside container
 
In article <OOqdnUQ8GIQlwc_TnZ2dnUVZ8hqdnZ2d@giganews.com>,
Leigh Johnston <leigh@i42.co.uk> wrote:
>On 22/08/2011 14:20, none Yannick Tremblay wrote:
>> In article<Xns9F43865A8800Dnonenonenone@69.16.186.52> ,
>> none<none@none.none> wrote:
>>> I've seen forum posts here and there asking "How do I create an STL
>>> container of arrays?" Or, equivalently, "How do I fix this syntax:"
>>>
>>> std::vector<float[20]> v;

>>
>> The obvious answer is:
>>
>> std::vector< std::vector<float> > v;

>
>Not always ideal as the array elements will not be contiguous (might be
>a requirement) and the overhead of the separate allocation for each
>array "row" might be undesirable.


Yes, by all mean, there *might* be special cases where
std::vector< std::vector<float> > v;
is not the ideal answer. However, it certainly should be one of the first
thing you consider.

The OP did not request contiguous memory nor particular performance
requirements. You should only use a more complex and potentially more
error prone construct if and only if profiling and analysis shows that
such a potentially more error prone construct is needed.

Yan


All times are GMT. The time now is 03:51 AM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.