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 ;