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:

    v.push_back(A(b1,c1));

    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...

    Cheers

    David
     
    David, Nov 27, 2004
    #1
    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
    {
    protected:
    A( A const& another ) { ... }
    A( ConstructorArguments const& a ) { ... };
    A& operator=( A const& other ) { ... }
    public:
    virtual ~A() { ... }
    };


    class AVec
    {
    private:
    static ConstructorArguments const* theArgs;

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

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

    std::vector<AWrapper> myVector;

    public:
    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
    out).
     
    Alf P. Steinbach, Nov 27, 2004
    #2
    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!

    Cheers

    David
     
    David, Nov 27, 2004
    #3
  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
    #4
  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
    #5
    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.