Как построить std :: string из std :: vector <char>?
115
Если не считать (очевидного) сначала создания строки в стиле C, а затем ее использования для создания std :: string, есть ли более быстрый / альтернативный / «лучший» способ инициализировать строку из вектора символов?
Можно ли это сделать без копирования? Другими словами, что-то, что делает то же самое, std::vector<char> v2(std::move(v))но с std::stringновым объектом.
tobi_s 02
Ответы:
197
Что ж, лучше всего использовать следующий конструктор:
За исключением VS2013, который утверждает во время выполнения о недопустимых итераторах, если вы не установили _ITERATOR_DEBUG_LEVEL=1(в этом случае, похоже, все работает нормально).
Кэмерон
35
В C ++ 11 вы можете сделать std::string(v.data())или, если ваш вектор не содержит '\0'в конце std::string(v.data(), v.size()),.
Я считаю, что даже с C ++ 98 можно использовать std :: string (& v [0]). Это, конечно, если вектор заканчивается нулем.
Джейми
1
@Jamie: Кстати, в C ++ 98 string(&v[0], v.size())тоже должно работать, но только после assert(not v.empty());, поскольку, если вектор пуст, оба v[0]и v.front()будут вызывать неопределенное поведение. В этом, помимо синтаксической простоты отсутствия использования оператора адресации, является реальное преимущество функции C ++ 11 data(), которая работает даже с пустым вектором.
Адам Х. Петерсон,
Совершенно верно. К сожалению, в обозримом будущем мой проект застрял на Visual Studio 2008. Правильно сначала проверить длину вектора.
Джейми
Если вектор не содержит '\ 0', std::string(v.data())строка может быть длиннее. Так что не используйте этот способ.
heLomaN
@heLomaN: Что случилось с тем std::string(v.data(), v.size()), что было прямо упомянуто в ответе именно по этой причине?
Sz.
12
std::string s(v.begin(), v.end());
Где v практически все, что можно итерировать. (В частности, begin () и end () должны возвращать InputIterators.)
Для полноты можно использовать другой способ std::string(&v[0])(хотя вам нужно убедиться, что ваша строка заканчивается нулем, и std::string(v.data())обычно это предпочтительнее.
Разница в том, что вы можете использовать предыдущий метод для передачи вектора функциям, которые хотят изменить буфер, чего вы не можете сделать с .data ().
Почему нельзя использовать data()для изменения буфера? Мне кажется, что если вы вызываете data()неконстантный вектор, он вернет a T *(и если ваш вектор const, 'v [0] `все T const &равно вернет a ).
Адам Х. Петерсон,
@ AdamH.Peterson это вроде недосмотр в стандарте. Данные Std :: vector имеют как константные, так и неконстантные функции, тогда как в текущем стандарте std :: string имеет только константную функцию: en.cppreference.com/w/cpp/string/basic_string/data Обратите внимание, что C ++ 17 добавляет неконстантную версию, так что это не может быть так до бесконечности - однако текущий стандарт гласит: «Изменение массива символов, доступ к которому осуществляется через данные, имеет неопределенное поведение».
Riot
Это было бы верно, если бы vэто была строка, но целевой тип - это строка и vвектор. (Но приятно видеть, что C ++ 17 обеспечивает четность строк с вектором.)
Адам Х. Петерсон,
@ AdamH.Peterson, конечно, ты прав. На вопрос был дан ответ некоторое время назад, я предполагал, что весь вопрос касается исключительно строк без проверки.
Riot
2
Мне нравится ответ Стефана (11 сентября 2013 г.), но я хотел бы сделать его немного сильнее:
Если вектор заканчивается нулевым ограничителем, вы не должны использовать (v.begin (), v.end ()): вы должны использовать v.data () (или & v [0] для тех, кто был до C ++ 17) ,
Если v не имеет нулевого терминатора, вы должны использовать (v.begin (), v.end ()).
Если вы используете begin () и end () и вектор действительно имеет завершающий ноль, вы получите, например, строку «abc \ 0», которая имеет длину 4, но на самом деле должна быть только «abc».
std::vector<char> v2(std::move(v))
но сstd::string
новым объектом.Ответы:
Что ж, лучше всего использовать следующий конструктор:
что приведет к чему-то вроде:
источник
Я думаю, ты можешь просто сделать
где MyVector - это ваш std :: vector.
источник
_ITERATOR_DEBUG_LEVEL=1
(в этом случае, похоже, все работает нормально).В C ++ 11 вы можете сделать
std::string(v.data())
или, если ваш вектор не содержит'\0'
в концеstd::string(v.data(), v.size())
,.источник
string(&v[0], v.size())
тоже должно работать, но только послеassert(not v.empty());
, поскольку, если вектор пуст, обаv[0]
иv.front()
будут вызывать неопределенное поведение. В этом, помимо синтаксической простоты отсутствия использования оператора адресации, является реальное преимущество функции C ++ 11data()
, которая работает даже с пустым вектором.std::string(v.data())
строка может быть длиннее. Так что не используйте этот способ.std::string(v.data(), v.size())
, что было прямо упомянуто в ответе именно по этой причине?Где v практически все, что можно итерировать. (В частности, begin () и end () должны возвращать InputIterators.)
источник
Для полноты можно использовать другой способ
std::string(&v[0])
(хотя вам нужно убедиться, что ваша строка заканчивается нулем, иstd::string(v.data())
обычно это предпочтительнее.Разница в том, что вы можете использовать предыдущий метод для передачи вектора функциям, которые хотят изменить буфер, чего вы не можете сделать с .data ().
источник
data()
для изменения буфера? Мне кажется, что если вы вызываетеdata()
неконстантный вектор, он вернет aT *
(и если ваш вектор const, 'v [0] `всеT const &
равно вернет a ).v
это была строка, но целевой тип - это строка иv
вектор. (Но приятно видеть, что C ++ 17 обеспечивает четность строк с вектором.)Мне нравится ответ Стефана (11 сентября 2013 г.), но я хотел бы сделать его немного сильнее:
Если вектор заканчивается нулевым ограничителем, вы не должны использовать (v.begin (), v.end ()): вы должны использовать v.data () (или & v [0] для тех, кто был до C ++ 17) ,
Если v не имеет нулевого терминатора, вы должны использовать (v.begin (), v.end ()).
Если вы используете begin () и end () и вектор действительно имеет завершающий ноль, вы получите, например, строку «abc \ 0», которая имеет длину 4, но на самом деле должна быть только «abc».
источник
источник