Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c++ > #8935 > unrolled thread

Array inside struct inside container

Started bynone <none@none.none>
First post2011-08-16 19:12 +0000
Last post2011-08-23 09:20 +0000
Articles 13 — 8 participants

Back to article view | Back to comp.lang.c++


Contents

  Array inside struct inside container none <none@none.none> - 2011-08-16 19:12 +0000
    Re: Array inside struct inside container Victor Bazarov <v.bazarov@comcast.invalid> - 2011-08-16 15:28 -0400
      Re: Array inside struct inside container none <none@none.none> - 2011-08-16 20:07 +0000
        Re: Array inside struct inside container Leigh Johnston <leigh@i42.co.uk> - 2011-08-16 21:18 +0100
          Re: Array inside struct inside container James Kanze <james.kanze@gmail.com> - 2011-08-22 11:01 -0700
            Re: Array inside struct inside container Leigh Johnston <leigh@i42.co.uk> - 2011-08-22 20:44 +0100
              Re: Array inside struct inside container Leigh Johnston <leigh@i42.co.uk> - 2011-08-22 20:51 +0100
        Re: Array inside struct inside container Alain Ketterlin <alain@dpt-info.u-strasbg.fr> - 2011-08-16 23:26 +0200
        Re: Array inside struct inside container "Bo Persson" <bop@gmb.dk> - 2011-08-17 12:29 +0200
          Re: Array inside struct inside container Juha Nieminen <nospam@thanks.invalid> - 2011-08-17 13:06 +0000
    Re: Array inside struct inside container yatremblay@bel1lin202.(none) (Yannick Tremblay) - 2011-08-22 13:20 +0000
      Re: Array inside struct inside container Leigh Johnston <leigh@i42.co.uk> - 2011-08-22 14:42 +0100
        Re: Array inside struct inside container yatremblay@bel1lin202.(none) (Yannick Tremblay) - 2011-08-23 09:20 +0000

#8935 — Array inside struct inside container

Fromnone <none@none.none>
Date2011-08-16 19:12 +0000
SubjectArray inside struct inside container
Message-ID<Xns9F43865A8800Dnonenonenone@69.16.186.52>
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?

[toc] | [next] | [standalone]


#8938

FromVictor Bazarov <v.bazarov@comcast.invalid>
Date2011-08-16 15:28 -0400
Message-ID<j2egda$5cc$1@dont-email.me>
In reply to#8935
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

[toc] | [prev] | [next] | [standalone]


#8939

Fromnone <none@none.none>
Date2011-08-16 20:07 +0000
Message-ID<Xns9F438F9EC556Bnonenonenone@69.16.186.52>
In reply to#8938
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.

[toc] | [prev] | [next] | [standalone]


#8940

FromLeigh Johnston <leigh@i42.co.uk>
Date2011-08-16 21:18 +0100
Message-ID<pZadnRq0y7wJTdfTnZ2dnUVZ7vCdnZ2d@giganews.com>
In reply to#8939
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.

/Leigh

[toc] | [prev] | [next] | [standalone]


#9189

FromJames Kanze <james.kanze@gmail.com>
Date2011-08-22 11:01 -0700
Message-ID<fae9016a-c8a7-4bae-a2fa-978fcb9234ba@df3g2000vbb.googlegroups.com>
In reply to#8940
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

[toc] | [prev] | [next] | [standalone]


#9192

FromLeigh Johnston <leigh@i42.co.uk>
Date2011-08-22 20:44 +0100
Message-ID<04adnVuQj_YDLM_TnZ2dnUVZ8iadnZ2d@giganews.com>
In reply to#9189
On 22/08/2011 19:01, James Kanze wrote:
> 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.
>

VS2008 emits REP MOVS.

 From Intel:

"Note that a REP STOS instruction is the
fastest way to initialize a large block of memory."

Not REP MOVS I know but perhaps an indicator; there is DMA and SSE to 
consider also.

/Leigh

[toc] | [prev] | [next] | [standalone]


#9194

FromLeigh Johnston <leigh@i42.co.uk>
Date2011-08-22 20:51 +0100
Message-ID<1sudnXJvDcPWLs_TnZ2dnUVZ8sGdnZ2d@giganews.com>
In reply to#9192
On 22/08/2011 20:44, Leigh Johnston wrote:
> On 22/08/2011 19:01, James Kanze wrote:
>> 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.
>>
>
> VS2008 emits REP MOVS.
>
>  From Intel:
>
> "Note that a REP STOS instruction is the
> fastest way to initialize a large block of memory."
>
> Not REP MOVS I know but perhaps an indicator; there is DMA and SSE to
> consider also.
>

Perhaps not DMA these days; I still occasionally live in the past.

/Leigh

[toc] | [prev] | [next] | [standalone]


#8942

FromAlain Ketterlin <alain@dpt-info.u-strasbg.fr>
Date2011-08-16 23:26 +0200
Message-ID<87k4ad6oa9.fsf@dpt-info.u-strasbg.fr>
In reply to#8939
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.

[toc] | [prev] | [next] | [standalone]


#8973

From"Bo Persson" <bop@gmb.dk>
Date2011-08-17 12:29 +0200
Message-ID<9b1jfoFehjU1@mid.individual.net>
In reply to#8939
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

[toc] | [prev] | [next] | [standalone]


#8982

FromJuha Nieminen <nospam@thanks.invalid>
Date2011-08-17 13:06 +0000
Message-ID<4e4bbcee$0$4367$7b1e8fa0@news.nbl.fi>
In reply to#8973
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.

[toc] | [prev] | [next] | [standalone]


#9173

Fromyatremblay@bel1lin202.(none) (Yannick Tremblay)
Date2011-08-22 13:20 +0000
Message-ID<j2tl32$ti4$1@dont-email.me>
In reply to#8935
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?

[toc] | [prev] | [next] | [standalone]


#9174

FromLeigh Johnston <leigh@i42.co.uk>
Date2011-08-22 14:42 +0100
Message-ID<OOqdnUQ8GIQlwc_TnZ2dnUVZ8hqdnZ2d@giganews.com>
In reply to#9173
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.

/Leigh

[toc] | [prev] | [next] | [standalone]


#9223

Fromyatremblay@bel1lin202.(none) (Yannick Tremblay)
Date2011-08-23 09:20 +0000
Message-ID<j2vrcn$b1m$1@dont-email.me>
In reply to#9174
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

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.c++


csiph-web