Подтвердить что ты не робот

Есть ли причины, по которым идиома StringPiece/StringRef не более популярна?

Из документации класса 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* в моем собственном коде этим классом? Есть ли что-нибудь подобное в стандартных библиотеках С++?

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

4b9b3361

Ответ 1

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

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

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

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

Ответ 2

Бит позже, но...

Идея за 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 * и весь char скопирован (например, с memcpy).

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

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

  • Google - StringPiece

  • boost - boost:: string_ref

  • LLVM - StringRef

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

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

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

Ответ 3

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

Ответ 4

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

Это не совсем универсально, как std::string, и это определенно не заменяет его.

Ответ 5

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

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

Ответ 6

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

(Не все купили в STL или std::string.)