Comparing 3 modern c++ ways to convert integral values to strings

前端 未结 1 1325
醉话见心
醉话见心 2020-12-01 06:46

I was trying to pick a standard way to convert integrals to strings, so I went on and did a small performance evaluation by measuring the execution time of

相关标签:
1条回答
  • 2020-12-01 07:28

    Question 1. Why is the string stream method consistently the worst?

    The classical mistake: creating a new stringstream every single time

    template<typename T> // 1. Using stringstream
    string StringFromIntegral_SS(T const &value) {
        thread_local stringstream ss;
        ss.str("");
        ss.clear();
        ss << value;
        return ss.str();
    }
    

    Question 2. Why is lexical cast consistently the best? Can we assume that this is the fastest implementation ?

    Because it's most specialized; and, no, faster implementations exist. FastFormat and Boost Spirit have competitive offerings, as far as I know.

    Update Boost Spirit Karma still easily beats the bunch:

    template<typename T> // 4. Karma to string
    std::string StringFromIntegral_K(T const &value) {
        thread_local auto const gen = boost::spirit::traits::create_generator<T>::call();
        thread_local char buf[20];
        char* it = buf;
        boost::spirit::karma::generate(it, gen, value);
        return std::string(buf, it);
    }
    

    Timings:

    C++ 11 method 111
    String stream method 103
    Lexical cast method 57
    Spirit Karma method 36
    Spirit Karma method with string_ref 13
    

    See it Live On Coliru Clang or GCC


    BONUS

    Just to goof off, a version using boost::string_ref is much faster still due the reduced allocations:

    template<typename T> // 5. Karma to string_ref
    boost::string_ref StringFromIntegral_KSR(T const &value) {
        thread_local auto const gen = boost::spirit::traits::create_generator<T>::call();
        thread_local char buf[20];
        char* it = buf;
        boost::spirit::karma::generate(it, gen, value);
        return boost::string_ref(buf, it-buf);
    }
    

    I've tested all modified methods for correctness using an asserting test loop:

    return measure<>::execution(
        //[&]() { for (auto const &i : v1) { func(i); }});
        [&]() { for (auto const &i : v1) { assert(func(i) == StringFromIntegral_LC(i)); }});
    
    0 讨论(0)
提交回复
热议问题