std::string itself realizes the management of character array and provides common functions of string class,
For example,
- lookup
- toggle case
- structure
wait
But std::string is a runtime calculation after all. As we all know, after std C++11, it supports calculating some constant values during compiler compilation, which can reduce runtime work and improve program performance.
The value that can be calculated at compile time is called compile time constant value, and the identifier in C + + is constexpr.
After all, the original intention of C + + language implementation is to maximize performance.
The performance of the runtime has been improved almost, so we can only squeeze the performance of the compiler to the greatest extent.
After all, compiling a program is only done once. As long as we do this well, we can save several calculations of the operation period, which is quite cost-effective.
To implement the string class at compile time, the boost library provides boost::string_ref class to improve the performance of std::string.
boost::string_ Another feature of ref is boost::string_ref does not copy the string, but directly assigns the character pointer, which is more efficient.
Let's look at the code
CMakeLists.txt
cmake_minimum_required(VERSION 2.6) project(lexical_cast) add_definitions(-std=c++14) include_directories("/usr/local/include") link_directories("/usr/local/lib") file( GLOB APP_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp) foreach( sourcefile ${APP_SOURCES} ) file(RELATIVE_PATH filename ${CMAKE_CURRENT_SOURCE_DIR} ${sourcefile}) string(REPLACE ".cpp" "" file ${filename}) add_executable(${file} ${sourcefile}) target_link_libraries(${file} boost_filesystem boost_regex boost_thread boost_system boost_serialization pthread boost_chrono) endforeach( sourcefile ${APP_SOURCES} )
main.cpp
#include <boost/utility/string_ref.hpp> #include <boost/algorithm/string/case_conv.hpp> #include <boost/algorithm/string/replace.hpp> #include <boost/lexical_cast.hpp> #include <iterator> #include <iostream> #include <algorithm> #include <string> #include <vector> #include <cassert> std::string between_str(const std::string& input, char starts, char ends) { auto pos_beg = std::find(input.begin(), input.end(), starts); if(pos_beg == input.end()) { return std::string(); } // Add 1 to the starting string position and discard the starts character ++ pos_beg; auto pos_end = std::find(pos_beg, input.end(), ends); // Don't use the last character. In fact, the index of the iterator is also the package left, not the package right, closed left and open right return std::string(pos_beg, pos_end); } boost::string_ref between(const boost::string_ref& input, char starts, char ends) { auto pos_beg = std::find(input.cbegin(), input.cend(), starts); if(pos_beg == input.cend()) { return boost::string_ref(); } ++ pos_beg; auto pos_end = std::find(pos_beg, input.cend(), ends); return boost::string_ref(pos_beg, pos_end - pos_beg); } void string_ref_init_examples() { // Initialize a string with const char *_ ref boost::string_ref r0("^_^"); // Initialize string with std::string_ref std::string O_O("O_O"); boost::string_ref r1 = O_O; // Initializing a string with std::vector_ ref std::vector<char> chars_vec(10, '#'); boost::string_ref r2(&chars_vec.front(), chars_vec.size()); // Avoid compiler unused warnings (void) r0; (void) r1; (void) r2; } void string_ref_algorithm_examples() { boost::string_ref r("O_O"); // Search_ Symbol std::find(r.cbegin(), r.cend(), '_'); // Convert to lowercase and print to standard output boost::to_lower_copy(std::ostream_iterator<char>(std::cout), r); std::cout << '\n'; // Print original string std::cout << r << '\n'; // Replace O with ^ and print boost::replace_all_copy(std::ostream_iterator<char>(std::cout), r, "O", "^"); std::cout << '\n'; // Verify boost:: decimal_ Cast available r = "100"; assert(boost::lexical_cast<int>(r) == 100); } int main(int argc, char* argv[]) { // Verify that const char * can be used to construct strings_ ref std::cout << between("Getting expression (between brackets)", '(', ')') << '\n'; // Verify that std::string can be used to construct string_ref std::string s("(expression)"); std::cout << between(s, '(', ')') << '\n'; string_ref_init_examples(); string_ref_algorithm_examples(); }
The program output is as follows
Implementation details
About boost:: String_ The implementation principle of ref class. You can check the source code,
typedef basic_string_ref<char, std::char_traits<char> > string_ref;
You can see boost::string_ref is actually basic_ string_ A typedef of Ref.
Let's take a look at basic_ string_ Implementation of ref class.
// basic_string_ref provides an empty constructor to initialize an empty string // Set the character pointer to null and the character length to 0 BOOST_CONSTEXPR basic_string_ref () BOOST_NOEXCEPT : ptr_(NULL), len_(0) {} // Default copy constructor, via string_ref construct string_ref BOOST_CONSTEXPR basic_string_ref (const basic_string_ref &rhs) BOOST_NOEXCEPT #ifndef BOOST_STRING_REF_NO_CXX11_DEFAULTED_NOEXCEPT_FUNCTIONS = default; // Construct based on const char * basic_string_ref(const charT* str) BOOST_NOEXCEPT : ptr_(str), len_(traits::length(str)) {} // Construct based on std::string template<typename Allocator> basic_string_ref(const std::basic_string<charT, traits, Allocator>& str) : ptr_(str.data()), len_(str.length()) {} // Construct based on char pointer and length BOOST_CONSTEXPR basic_string_ref(const charT* str, size_type len) BOOST_NOEXCEPT : ptr_(str), len_(len) {}
You can see basic_ string_ The overloaded constructor of ref class implements various construction methods, which can interoperate with std::string, const char * and character array (these types can be implicitly converted to basic_string_ref).
In addition, some functions realize constant calculation at compile time to improve performance.
Let's take a look at basic_ string_ How ref supports set class algorithms,
To support stl's set class algorithm, you only need to implement the iterative methods of begin and end
// iterators // Implement the begin, end, cbegin and cend methods of compiling time value BOOST_CONSTEXPR const_iterator begin() const { return ptr_; } BOOST_CONSTEXPR const_iterator cbegin() const { return ptr_; } BOOST_CONSTEXPR const_iterator end() const { return ptr_ + len_; } BOOST_CONSTEXPR const_iterator cend() const { return ptr_ + len_; } // Implement the direction iterator rbegin, rend const_reverse_iterator rbegin() const { return const_reverse_iterator (end()); } const_reverse_iterator crbegin() const { return const_reverse_iterator (end()); } const_reverse_iterator rend() const { return const_reverse_iterator (begin()); } const_reverse_iterator crend() const { return const_reverse_iterator (begin()); }
Finally, to make boost::string_ref can be directly implicitly typed into std::string, and the operator std::string operator is explicitly overloaded, so that they can interoperate (std::string and boost::string_ref can be used instead).
#ifndef BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS // Overload operator std::string operator template<typename Allocator> explicit operator std::basic_string<charT, traits, Allocator>() const { return std::basic_string<charT, traits, Allocator> ( begin(), end()); } #endif