Я просто думал о реализации std::string::substr
. Он возвращает новый объект std::string
, который кажется мне немного расточительным. Почему бы не вернуть объект, который ссылается на содержимое исходной строки и может быть неявно назначен для std::string
? Это своего рода ленивая оценка фактического копирования. Такой класс может выглядеть примерно так:Можно ли разрешить эту оптимизацию при реализации std :: string?
template <class Ch, class Tr, class A>
class string_ref {
public:
// not important yet, but *looks* like basic_string's for the most part
private:
const basic_string<Ch, Tr, A> &s_;
const size_type pos_;
const size_type len_;
};
Общедоступный интерфейс этого класса будет имитировать все операции только для чтения вещественного std::string
, поэтому использование будет бесшовным. std::string
может иметь новый конструктор, который принимает string_ref
, чтобы пользователь никогда не был более мудрее. В тот момент, когда вы пытаетесь «сохранить» результат, вы в конечном итоге создаете копию, поэтому никаких реальных проблем с ссылкой, указывающей на данные, а затем ее изменения за ее спиной не возникает.
Идея заключается в том, что такой код:
std::string s1 = "hello world";
std::string s2 = "world";
if(s1.substr(6) == s2) {
std::cout << "match!" << std::endl;
}
не будет иметь не более 2 std::string
объектов, построенных в общей сложности. Это похоже на полезную оптимизацию для кода, который выполняет много строковых манипуляций. Конечно, это относится не только к std::string
, но и к любому типу, который может вернуть подмножество его содержимого.
Насколько я знаю, никакие реализации этого не делают.
Я предполагаю, что сердцевина вопроса:
Учитывая класс, который может быть неявно преобразован в std::string
по мере необходимости, было бы, соответствующей стандарту для библиотеки писателя, чтобы изменить прототип члена в тип возврата? Или, в более общем плане, у библиотекарей есть возможность вернуть «прокси-объекты» вместо обычных объектов в этих типах случаев в качестве оптимизации?
Моя внутренность - это то, что это не разрешено и что прототипы должны точно совпадать. Учитывая, что вы не можете перегружать только возвращаемый тип, это не помешает библиотечным писателям воспользоваться этими ситуациями. Как я уже сказал, я думаю, что ответ отрицательный, но я решил, что спрошу :-).
@Evan: вы можете прочитать язык программирования C++ - он представляет собой реализацию этой концепции. Тем не менее, такой string_ref легко недействителен, а копирование часто относительно дешево, поэтому обычно люди с удовольствием копируют в новую строку. Когда я реализую такой класс, я стараюсь сделать это в терминах const char * и size, что делает его более широко применимым (например, накладывая его на файлы с отображением памяти, данные const char [] и т. Д.). Если вам нужна подстрока, которая может быть изменена независимо от источника, тогда все быстро усложняется, особенно в поточных средах .... –
@ Тони: как 'llvm :: StringRef'? –
Вы не думаете, что реализация COW std :: string еще не повторно использует буфер исходной строки, когда вы выполняете substr(). –