вопрос, является ли код
std::size_t required_size;
f(nullptr, &required_size);
std::string s;
s.resize(required_size);
f(&s[0], &required_size);
безопасен.
Это зависит от того, C++ стандарт один предполагает, но так как это Неопределенное поведение для случая required_size
= 0 в C++ 03 и C++ 98, общий ответ нет, это не безопасно в целом.
В C++ 03 std::string
формально не гарантирован иметь непрерывный буфер, но на практике все сохранившиеся реализации имели непрерывный буфер.Во всяком случае, теперь после C++ 11, где в стандарте была включена стандартная встроенная поддержка буфера, не будет никаких новых реализаций C++ 03 с несмежным буфером. Следовательно, это не проблема.
Проблема скорее в том, что 03 std::basic_string::operator[]
C++ была определена следующим образом:
C++ 03 §21.3.4/1:
”Возвращает: Если pos < size()
, возвращает data()[pos]
. В противном случае, если pos == size()
, версия const
возвращает charT()
. В противном случае поведение не определено.
Таким образом, для не- const
строки s
размера 0, в C++ 03 это Неопределенное поведение ™ сделать индексацию s[0]
.
В С ++ 11 соответствующий пункт §21.4.3/2 говорит вместо того, что результат “ *(begin() + pos)
, если pos < size()
, в противном случае это ссылка на объект типа T
со значением charT()
; ссылочное значение не должно изменяться. ”
Вот код, который работает независимо от того, какой стандарт C++ компилятор использует:
std::size_t required_size;
f(NULL, &required_size); // Establish required buffer size.
if(required_size > 0)
{
std::string s(required_size, '#');
f(&s[0], &required_size);
s.resize(strlen(&s[0]));
}
Что случилось с этим? Это довольно распространенный шаблон при взаимодействии с C API. –
Почему бы не использовать 's.c_str()'? – Petr
см. Http://herbsutter.com/2008/04/07/cringe-not-vectors-are-guaranteed-to-be-contiguous/#comment-483 –