calling placement new for elements of a deque

Discussion in 'C++' started by hbdevelop1, Feb 27, 2014.

  1. hbdevelop1

    hbdevelop1 Guest

    Hello
    For optimisation reasons, I am re-using not used objects in my deque for new objects.
    I am doing that this way :
    void Score::Add(const char *str, Coordinates &sp)
    {
    for(deque<Text>::iterator it=scores.begin();it!=scores.end(); ++it)
    {
    if(it->notUsed==1)
    {
    it->Reset(str,sp);
    return;
    }
    }

    scores.push_back(Text(str,sp));
    }

    I thought it would be more convenient to call the placement new on the notUsed object instead of Reset.
    How can I do this ?
    How can I get the address of the not used object so I can use it in the new placement operator?


    Thank you in advance
     
    hbdevelop1, Feb 27, 2014
    #1
    1. Advertisements

  2. You can get a reference to the object through operator* of the iterator.
    Then you can use the operator& to get the address of the object. Keep
    in mind, however, that generally the constructor calls need to match the
    destructor calls, so don't forget to destroy the object using a direct
    call to the destructor before constructing a new one there. Something like

    if (it->notUsed == 1)
    {
    Text *pUnused = &(*it);
    pUnused->~Text(); // destroy
    new (pUnused) Text(str, sp);
    return;
    }

    Remember to include <memory> for placement new operator.

    Not sure this is the best approach, though. Why do you think that using
    Reset is inconvenient?

    V
     
    Victor Bazarov, Feb 27, 2014
    #2
    1. Advertisements

  3. hbdevelop1

    red floyd Guest

    The only reason I can see for using placement new instead of a reset is
    that some const members may need updating for the new data. Otherwise
    a reset should be fine.
     
    red floyd, Feb 27, 2014
    #3
  4. hbdevelop1

    hbdevelop1 Guest

    The reason why I don't want to use Reset is because it holds the same code as the constructor and is only used in this case.
    So I just wondered if I could get rid of Reset and use the constructor, for both, when pushing for the first time and when resetting.
    And now, red floyd has given another reason why I might want to use the placement new in future.

    Thank you very much Victor and red for your help and constructive feed back

    hbdevelop1
     
    hbdevelop1, Feb 27, 2014
    #4
  5. hbdevelop1

    red floyd Guest

    1. Please don't top-post.

    2. I'd be VERRRRY careful about using placement new for that unless
    you ABSOLUTELY POSITIVELY need to do so. I would definitely prefer
    a Reset() function, or even an operator=(). Remember, readability
    and maintainability trump cleverness every single time.

    Also remember Hoare's law (also attributed to Knuth, or vice-versa):
    "Premature optimization is the root of all evil."

    Do you *really* need to do this "for efficency reasons"? Have you
    actually benchmarked to see if your insertion/deletion code is a
    bottleneck? Would an alternate data structure such as a std::list<>
    perhaps suit your purposes better?

    Think about that before embarking on this path.
     
    red floyd, Feb 27, 2014
    #5
  6. hbdevelop1

    hbdevelop1 Guest

    I used "optimization" for the wrong thing. In fact I wanted to mean writing less code, and not having two functions doing almost the same thing.

    I do agree with you on going about optimizing code using figures and through profiling.
    I liked your point on readability and maintainability and on thinking about other data structure.

    Thank you for your advice on being pragmatic in optimization
     
    hbdevelop1, Mar 3, 2014
    #6
  7. hbdevelop1

    Öö Tiib Guest

    Others have already answered about that placement new.

    Regardless if you use it or not I wanted to comment that typically such
    reuse is done with linked list of unused elements (not by for-cycling over
    whole container). It is because if the container is small and rarely added
    to / erased from then the whole reuse is likely not worth it ... but
    otherwise cycling in it is also wasteful. Something like that:

    void Score::Add( const char *str, Coordinates &sp )
    {
    Text* toReplace = firstUnused;
    if ( toReplace == nullptr )
    {
    scores.emplace_back( str, sp );
    }
    else
    {
    firstUnused = ( toReplace->nextUnused == toReplace ) ? nullptr : toReplace->nextUnused;
    toReplace->swap( Text( str, sp ) );
    }
    }

    That involves that you build the linked list when elements become
    unused.
     
    Öö Tiib, Mar 3, 2014
    #7
    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.