fastest way to convert a std::vector to another std::vector

后端 未结 8 2415
春和景丽
春和景丽 2020-12-03 14:08

What is the fastest way (if there is any other) to convert a std::vector from one datatype to another (with the idea to save space)? For example:

std::vector         


        
8条回答
  •  一个人的身影
    2020-12-03 14:32

    There's no way to avoid the copy, since a std::vector is a distinct type from std::vector, and there's no way for them to share the memory. Other than that, it depends on how the data is mapped. If the mapping corresponds to an implicit conversion (e.g. unsigned short to bool), then simply creating a new vector using the begin and end iterators from the old will do the trick:

    std::vector newV( oldV.begin(), oldV.end() );
    

    If the mapping isn't just an implicit conversion (and this includes cases where you want to verify things; e.g. that the unsigned short does contain only 0 or 1), then it gets more complicated. The obvious solution would be to use std::transform:

    std::vector newV;
    newV.reserve( oldV.size() );    //  avoids unnecessary reallocations
    std::transform( oldV.begin(), oldV.end(),
                    std::back_inserter( newV ),
                    TranformationObject() );
    

    , where TranformationObject is a functional object which does the transformation, e.g.:

    struct ToBool : public std::unary_function
    {
        bool operator()( unsigned short original ) const
        {
            if ( original != 0 && original != 1 )
                throw Something();
            return original != 0;
        }
    };
    

    (Note that I'm just using this transformation function as an example. If the only thing which distinguishes the transformation function from an implicit conversion is the verification, it might be faster to verify all of the values in oldV first, using std::for_each, and then use the two iterator constructor above.)

    Depending on the cost of default constructing the target type, it may be faster to create the new vector with the correct size, then overwrite it:

    std::vector newV( oldV.size() );
    std::transform( oldV.begin(), oldV.end(),
                    newV.begin(),
                    TranformationObject() );
    

    Finally, another possibility would be to use a boost::transform_iterator. Something like:

    std::vector newV(
        boost::make_transform_iterator( oldV.begin(), TranformationObject() ),
        boost::make_transform_iterator( oldV.end(), TranformationObject() ) );
    

    In many ways, this is the solution I prefer; depending on how boost::transform_iterator has been implemented, it could also be the fastest.

提交回复
热议问题