In place construction without placement new

Discussion in 'C++' started by David, Nov 27, 2004.

  1. David

    David Guest

    Suppose that I have a class A with a constructor A(B b, C c) and I want
    to make a vector of A's. Also, suppose that A's are VERY expensive to
    construct, copy, assign. I also want to have a very many vectors of A's
    and cannot afford to store a smart pointer to each A as the type in my
    vectors.. So I want to write something like:


    and not have a sequence which goes like:

    .... make space for an A in v at v...
    construct A() in v
    destruct v
    assign A(b1,c1) to v

    Unfortunately, this is the behaviour I am seeing in my compiler. I want:

    .... make space for an A in v at v...
    construct A(b1,c1) in v

    Is there any known way to ensure that compilers will give the latter
    code? I have a work around, but it is clunky...


    David, Nov 27, 2004
    1. Advertisements

  2. * David:
    Then a raw vector is contraindicated.

    You don't: no matter what you do you will then have construction of the
    argument followed by copying of the argument.

    That is a quality-of-implementation issue. The implementation should
    just copy-construct the argument in the new space. However, given your
    earlier remarks even that seems to be one copy-operation too much.

    No, but you can easily do it yourself.

    Off the cuff:

    class ConstructorArguments { ... };

    class A
    A( A const& another ) { ... }
    A( ConstructorArguments const& a ) { ... };
    A& operator=( A const& other ) { ... }
    virtual ~A() { ... }

    class AVec
    static ConstructorArguments const* theArgs;

    class AWrapper: public A
    AWrapper(): A( *theArgs ) {}

    // Required for std::vector usage.
    AWrapper( AWrapper const& another ): A( another ) {}
    AWrapper& operator=( AWrapper const& other ) { ... }

    std::vector<AWrapper> myVector;

    AVec( size_t aCapacity ) { myVector.reserve( aCapacity ); }

    void pushBackNew( ConstructorArguments const& args )
    if( myVector.size() == myVector.capacity() )
    throw std::runtime_error( "Ooops, this would copy" );
    theArgs = &args;
    myVector.resize( myVector.size() + 1 );

    A& operator[]( size_t i ) { return myVector; }
    A const& operator[]( size_t i ) const { return myVector; }

    assuming 'resize' constructs and does not subsequently assign (check it
    Alf P. Steinbach, Nov 27, 2004
    1. Advertisements

  3. David

    David Guest

    Very large numbers of them all of which are unique pointers (i.e. apart
    from algorithm use, their use count will sit at 1 for the majority of
    their existence). So I'd prefer to store them by value, avoiding the
    time and space overhead of a smart pointer for each of them and just
    passing iterators/references to the items in the vectors.

    Yes I want to avoid all copying.

    Thanks for the suggestion!

    I checked out the implementation and it calls insert (or erase, which
    won't happen in my case) which then calls std::fill_n() which uses
    operator=. I think that I then am back to quality of implementation? My
    'clunky' solution is not all that different from your solution. I think
    I may need to sleep on this one!


    David, Nov 27, 2004
  4. * David:
    Well then, give it an AWrapper::eek:perator=. One that doesn't do
    anything. For the code to be portable you should do that anyway, now
    that I think of it.
    Alf P. Steinbach, Nov 27, 2004
  5. * Alf P. Steinbach:
    Forgot to add: class A then needs a constructor that gives it a dummy
    state, invoked by default constructor of AWrapper.
    Alf P. Steinbach, Nov 27, 2004
    1. Advertisements

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.