Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c++ > #8935 > unrolled thread
| Started by | none <none@none.none> |
|---|---|
| First post | 2011-08-16 19:12 +0000 |
| Last post | 2011-08-23 09:20 +0000 |
| Articles | 13 — 8 participants |
Back to article view | Back to comp.lang.c++
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
| From | none <none@none.none> |
|---|---|
| Date | 2011-08-16 19:12 +0000 |
| Subject | Array 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]
| From | Victor Bazarov <v.bazarov@comcast.invalid> |
|---|---|
| Date | 2011-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]
| From | none <none@none.none> |
|---|---|
| Date | 2011-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]
| From | Leigh Johnston <leigh@i42.co.uk> |
|---|---|
| Date | 2011-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]
| From | James Kanze <james.kanze@gmail.com> |
|---|---|
| Date | 2011-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]
| From | Leigh Johnston <leigh@i42.co.uk> |
|---|---|
| Date | 2011-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]
| From | Leigh Johnston <leigh@i42.co.uk> |
|---|---|
| Date | 2011-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]
| From | Alain Ketterlin <alain@dpt-info.u-strasbg.fr> |
|---|---|
| Date | 2011-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]
| From | "Bo Persson" <bop@gmb.dk> |
|---|---|
| Date | 2011-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]
| From | Juha Nieminen <nospam@thanks.invalid> |
|---|---|
| Date | 2011-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]
| From | yatremblay@bel1lin202.(none) (Yannick Tremblay) |
|---|---|
| Date | 2011-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]
| From | Leigh Johnston <leigh@i42.co.uk> |
|---|---|
| Date | 2011-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]
| From | yatremblay@bel1lin202.(none) (Yannick Tremblay) |
|---|---|
| Date | 2011-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