CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 15 of 27

Threaded View

  1. #1
    Join Date
    Jun 2009
    Location
    France
    Posts
    2,513

    A better vector trim with move semantics

    I love having trimmed vectors. If there is one thing that makes me feel more smug than using reserve before inserting, its trimming when I can't know in advance how much to reserve. I've always had this useful function in my personal library:

    Code:
    template <typename T>
    void trim_vector(std::vector<T>& io_vector)
    {
      if(io_vector.size() == io_vector.capacity())
        {return;}
    
      std::vector<T>(io_vector).swap(io_vector);
    }
    If you are not familiar with vector trimming, then you can look here, or read yourself some Scott Meyers Effective STL. Basically, It copy constructs a brand new vector of the right size, and then swaps the contents.

    I've been playing around with move recently, and while I've always considered trim to be expensive, it now looks to me to be excessively expensive. Why make a copy of each element, when you could be moving them?

    The problem is that the solution is not trivial: Simply moving the vector will not have the desired effect, as the new vector will just be the old vector. You want to move all the elements of the old vector into the new one, without touching the allocated space in which the elements are.

    So I rewrote my vector_trim. The trick is to use the iterator constructor, as well as some move_iterator magic:
    EDIT: More optimization
    Code:
    template <typename T>
    void trim_vector(std::vector<T>& io_vector)
    {
      if(io_vector.size() == io_vector.capacity())
        {return;}
    
      io_vector = //Since the temporary vector is an R-value, this will call operator(std::vector&&), ie, a move
        std::vector<T>(
          std::make_move_iterator(io_vector.begin()),
          std::make_move_iterator(io_vector.end()),
          io_vector.get_allocator()
        );
    }
    This code has strictly no overhead compared to the old one in regards to non-move-able objects, but is magnitudes faster for move-able objects.

    A very interesting side effect is that it allows the trimming of vectors whose objects are not copy constructable (think vector<unique_ptr>), which was not the case with the old code.

    There, I hope whoever reads this will find it useful.
    Last edited by monarch_dodra; January 6th, 2011 at 05:35 AM.
    Is your question related to IO?
    Read this C++ FAQ article at parashift by Marshall Cline. In particular points 1-6.
    It will explain how to correctly deal with IO, how to validate input, and why you shouldn't count on "while(!in.eof())". And it always makes for excellent reading.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured