Array inside struct inside container

Discussion in 'C++' started by none, Aug 16, 2011.

  1. none

    none Guest

    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?
    none, Aug 16, 2011
    #1
    1. Advertising

  2. 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::eek:p=\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
    Victor Bazarov, Aug 16, 2011
    #2
    1. Advertising

  3. none

    none Guest

    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.
    none, Aug 16, 2011
    #3
  4. 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.
    Alain Ketterlin, Aug 16, 2011
    #4
  5. none

    Bo Persson Guest

    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
    Bo Persson, Aug 17, 2011
    #5
  6. Bo Persson <> 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.
    Juha Nieminen, Aug 17, 2011
    #6
  7. none

    none Guest

    In article <Xns9F43865A8800Dnonenonenone@69.16.186.52>,
    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?
    none, Aug 22, 2011
    #7
  8. none

    James Kanze Guest

    On Aug 16, 9:18 pm, Leigh Johnston <> 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
    James Kanze, Aug 22, 2011
    #8
  9. none

    none Guest

    In article <>,
    Leigh Johnston <> wrote:
    >On 22/08/2011 14:20, none Yannick Tremblay wrote:
    >> In article<Xns9F43865A8800Dnonenonenone@69.16.186.52>,
    >> 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
    none, Aug 23, 2011
    #9
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Chris Fogelklou
    Replies:
    36
    Views:
    1,373
    Chris Fogelklou
    Apr 20, 2004
  2. Mark McIntyre

    C beginner: struct inside another struct...

    Mark McIntyre, Apr 21, 2006, in forum: C Programming
    Replies:
    5
    Views:
    667
    Yourko
    Apr 23, 2006
  3. monkeydragon

    Struct inside a struct

    monkeydragon, Dec 18, 2005, in forum: C++
    Replies:
    3
    Views:
    17,859
    Rolf Magnus
    Dec 20, 2005
  4. wolverine
    Replies:
    2
    Views:
    450
    Marcus Kwok
    Jul 24, 2006
  5. Tuan  Bui
    Replies:
    14
    Views:
    472
    it_says_BALLS_on_your forehead
    Jul 29, 2005
Loading...

Share This Page