Есть ли причины, по которым идиома StringPiece / StringRef не так популярна? - PullRequest
13 голосов
/ 31 января 2010

Из документации StringPiece класса в исходном коде Chromium :

// A string-like object that points to a sized piece of memory.
//
// Functions or methods may use const StringPiece& parameters to accept either
// a "const char*" or a "string" value that will be implicitly converted to
// a StringPiece.  
//
// Systematic usage of StringPiece is encouraged as it will reduce unnecessary
// conversions from "const char*" to "string" and back again.

Пример использования:

void foo(StringPiece const & str) // Pass by ref. is probably not needed
{
   // str has same interface of const std::string
}

int main()
{
    string bar("bar");
    foo(bar); // OK, no mem. alloc.

    // No mem. alloc. either, would be if arg. of "foo" was std::string
    foo("baz");  
}

Это кажется такой важной и очевидной оптимизацией, что я не могу понять, почему она не получила более широкого распространения и почему класс, подобный StringPiece, еще не входит в стандарт.

Есть ли причины, по которым я не должен заменять использование параметров string и char* в моем собственном коде этим классом? Есть ли что-нибудь подобное в стандартных библиотеках C ++?

UPDATE . Я узнал, что источник LLVM использует похожую концепцию: класс StringRef .

Ответы [ 6 ]

8 голосов
/ 28 сентября 2015

Чуть позже, но ...

Идея, лежащая в основе StringPiece, очень хорошая. Класс может захватывать как std::string, так и const char * и передавать их в функцию. Вот пример:

void process(const StringRef s){
   // do something
}

process("Hello"); // const char *
std::string s = "Hello";
process(s); // std::string
process(std::string("Hello")); // std::string rvalue

Если функция принята std::string вы фактически создаете временный объект, если передаете const char * и копируется весь символ (например, с memcpy).

Вам также не нужно беспокоиться о времени жизни, потому что вы передаете StringRef в функцию / метод.

Есть такой класс в:

  • Google - StringPiece

  • boost - boost :: string_ref

  • LLVM - StringRef

Мою собственную (неполную) реализацию можно увидеть здесь:
https://github.com/nmmmnu/HM3/blob/master/include/stringref.h

Обновление 2016:

В C ++ 17 есть std::string_view. Я не изучал это в деталях, но в целом это имеет ту же идею. Также как и в моей реализации, он имеет constexpr c-tor, поэтому вы можете создавать объекты во время компиляции и использовать его вместе с другими constexpr функциями.

4 голосов
/ 03 декабря 2013

На этот вопрос уже получен очень хороший ответ, но, чтобы дать больше контекста, шаблон StringPiece очень широко используется внутри Google и используется уже много лет. Настоятельно рекомендуется в правилах кодирования Google, поэтому почти наверняка Chrome (и впоследствии Chromium) принял его.

2 голосов
/ 05 февраля 2010

StringPiece сохраняет указатель на строковые данные, которые передаются его конструктору. Таким образом, он полагается, что время жизни этой строки будет больше, чем StringPiece. Это гарантируется, если вы используете StringPiece в качестве параметра функции; это не так, если вы храните копию строки, например, в классе.

Он не так универсален, как std :: string, и определенно не является заменой.

0 голосов
/ 30 мая 2014

StringPiece - это здорово, но пьесы не заканчиваются на нуль. Если вам нужно перейти к интерфейсам более низкого уровня, которые принимают строки с нулевым символом в конце, вам необходимо скопировать этот фрагмент в строку с нулевым символом в конце.

(Не каждый купил в STL или std :: string.)

0 голосов
/ 05 февраля 2010

Потому что зачем? При копировании и / или передаче по ссылке обычно можно также избежать выделения памяти для std::string.

Строковая ситуация в C ++ достаточно запутанная, без добавления еще большего количества строковых классов.

Если язык должен был быть переработан с нуля, или если обратная совместимость не была проблемой, то это одно из многих возможных улучшений, которые можно было бы сделать для обработки строк в C ++. Но теперь, когда мы застряли как с char*, так и с std::string, добавление класса стиля stringref в микс вызовет много путаницы с ограниченным преимуществом.

Помимо этого, разве такой же эффект не достигается более идиоматически с парой итераторов? Если я хочу передать последовательность символов, принадлежащих ли они строке или char*, почему бы мне не использовать пару итераторов для их разделения?

0 голосов
/ 31 января 2010

Стандарт пытается отойти от const char * в пользу строки в целом, поэтому добавлять дополнительные параметры для преобразования бесполезно.

Также обратите внимание, что хорошо сформированная программа должна использовать либо string, либо const char * вокруг;).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...