Copyright © 2012 Marshall Clow
Повышаю. StringRef является реализацией Джеффри ЯскинаN3442: string_ref: ссылка на строку.
Когда вы анализируете / обрабатываете строки из какого-либо внешнего источника, часто вы хотите передать часть текста процедуре для специализированной обработки. Канонический способ сделать это как<std::string>, но у этого есть определенные недостатки:
1) Если вы обрабатываете буфер текста (например, HTTP-ответ или содержимое файла), то вам нужно создать строку из текста, который вы хотите передать, которая включает в себя выделение памяти и копирование данных.
2) если рутина получает постоянную<std::string>и хочет передать часть этой строки другой рутине, то она должна создать новую строку этой подстроки.
3) Рутина получает постоянную<std::string>и хочет вернуть часть строки, затем она должна создать новую строку для возвращения.
<string_ref>предназначен для решения этих задач. A<string_ref>— это ссылка только для чтения на непрерывную последовательность символов и обеспечивает большую часть функциональности<std::string>. А<string_ref>дешево создавать, копировать и передавать по стоимости, потому что он фактически не владеет хранилищем, на которое он указывает.
<string_ref>реализуется как небольшая структура, содержащая указатель на начало данных символов и счетчик.<string_ref>Дешево создавать и дешево копировать.
<string_ref>действует как контейнер; он включает в себя все методы, которые вы ожидаете в контейнере, включая поддержку итераций<operator[]>,<at>и<size>. Он может быть использован с любым из алгоритмов на основе итератора в STL - до тех пор, пока вам не нужно изменять базовые данные<sort>и<remove>, например, не будет работать.
Помимо общей функциональности контейнера,<string_ref>обеспечивает подмножество интерфейса<std::string>. Это позволяет легко заменить параметры типа<const
std::string&>на<boost::string_ref>. Как и<std::string>,<string_ref>имеет статическую переменную элемента, названную<npos>, чтобы обозначить результат неудачных поисков и означать «конец».
Поскольку<string_ref>не владеет данными, которые он «указывает», он вводит пожизненные проблемы в код, который его использует. Программист должен гарантировать, что данные, на которые ссылается<string_ref>, существуют до тех пор, пока существует<string_ref>.
Интеграция<string_ref>в ваш код довольно проста. Где бы вы ни проходили<const
std::string&>или<std::string>в качестве параметра, это кандидат на прохождение<boost::string_ref>.
std::string extract_part ( const std::string &bar ) {
return bar.substr ( 2, 3 );
}
if ( extract_part ( "ABCDEFG" ).front() == 'C' ) { }
Давайте разберемся, что происходит в этом (придуманном) примере.
Во-первых, временная строка создается из строки буквально<"ABCDEFG">, и она передается (по ссылке) в рутину<extract_part>. Затем создается вторая строка в призыве<std::string::substr>и возвращается к<extract_part>(эта копия может быть оставлена RVO).<extract_part>возвращает эту строку обратно вызывающему (опять же, эта копия может ускользнуть). Первая временная строка размещается, а<front>вызывается на вторую строку, а затем она также размещается.
Созданы две<std::string>и две копирующие операции. Это (потенциально) четыре распределения памяти и распределения, а также связанное с ними копирование данных.
Теперь рассмотрим тот же код<string_ref>:
boost::string_ref extract_part ( boost::string_ref bar ) {
return bar.substr ( 2, 3 );
}
if ( extract_part ( "ABCDEFG" ).front() == "C" ) { }
Никаких выделений памяти. Никакого копирования данных персонажей. Никаких изменений в коде, кроме типов. Есть два<string_ref>созданных и два<string_ref>скопированных, но это дешевые операции.
Файл заголовка «string_ref.hpp» определяет шаблон<boost::basic_string_ref>, а четыре специализации — для<char>/<wchar_t>/<char16_t>/<char32_t>.
<#include<boost/utility/string_ref.hpp>>
Строительство и копирование:
BOOST_CONSTEXPR basic_string_ref ();
BOOST_CONSTEXPR basic_string_ref(const charT* str);
BOOST_CONSTEXPR basic_string_ref(const charT* str, size_type len);
template<typename Allocator>
basic_string_ref(const std::basic_string<charT, traits, Allocator>& str);
basic_string_ref (const basic_string_ref &rhs);
basic_string_ref& operator=(const basic_string_ref &rhs);
<string_ref>не определяет ни конструктора движения, ни оператора назначения движения, потому что копирование<string_ref>просто дешево.
Основные контейнероподобные функции:
BOOST_CONSTEXPR size_type size() const ;
BOOST_CONSTEXPR size_type length() const ;
BOOST_CONSTEXPR size_type max_size() const ;
BOOST_CONSTEXPR bool empty() const ;
BOOST_CONSTEXPR const_iterator begin() const ;
BOOST_CONSTEXPR const_iterator cbegin() const ;
BOOST_CONSTEXPR const_iterator end() const ;
BOOST_CONSTEXPR const_iterator cend() const ;
const_reverse_iterator rbegin() const ;
const_reverse_iterator crbegin() const ;
const_reverse_iterator rend() const ;
const_reverse_iterator crend() const ;
Доступ к отдельным элементам (все из которых конст):
BOOST_CONSTEXPR const charT& operator[](size_type pos) const ;
const charT& at(size_t pos) const ;
BOOST_CONSTEXPR const charT& front() const ;
BOOST_CONSTEXPR const charT& back() const ;
BOOST_CONSTEXPR const charT* data() const ;
Изменение<string_ref>(но не базовые данные):
void clear();
void remove_prefix(size_type n);
void remove_suffix(size_type n);
Поиск:
size_type find(basic_string_ref s) const ;
size_type find(charT c) const ;
size_type rfind(basic_string_ref s) const ;
size_type rfind(charT c) const ;
size_type find_first_of(charT c) const ;
size_type find_last_of (charT c) const ;
size_type find_first_of(basic_string_ref s) const ;
size_type find_last_of(basic_string_ref s) const ;
size_type find_first_not_of(basic_string_ref s) const ;
size_type find_first_not_of(charT c) const ;
size_type find_last_not_of(basic_string_ref s) const ;
size_type find_last_not_of(charT c) const ;
Струнные операции:
BOOST_CONSTEXPR basic_string_ref substr(size_type pos, size_type n=npos) const ;
bool starts_with(charT c) const ;
bool starts_with(basic_string_ref x) const ;
bool ends_with(charT c) const ;
bool ends_with(basic_string_ref x) const ;