Здравствуйте, indee, Вы писали: I>Почему mystr пустая и длина = 0 (mystr.length())?
У тебя в программе неопределённое поведение. Оно может проявляться множеством способов, в том числе и таким.
Когда ты записываешь что-то в буфер строки s напрямую, то запись можно делать только в область памяти от s.data() до s.data()+s.size() причём в последнюю позицию s.data()+s.size() можно записывать только '\0'.
В функции test это требование нарушается и запись идёт за пределы этого диапазона, перезатирая чужие данные.
Скрытый текст
Технически, длина строки mystr не меняется и остаётся нулём, так как она хранится отдельно и от содержимого буфера [ s.data(), s.data()+s.size() ] не зависит. А функция test никак не обновляет размер. Но это деталь реализации. И она не особо важна, пока в программе есть неопределённое поведение.
I>// mystr = mystr.c_str(); после этого все ОК
I>// std::cout << mystr << " Length = " << mystr.length() << std::endl;mystr = mystr.c_str();
Здравствуйте, indee, Вы писали:
I>Почему mystr пустая и длина = 0 (mystr.length())?
I>Спасибо!
Это вам еще повезло что она просто пустая, при таком подходе обычно программа падает.
Давайте попробуем пройтись по пунктах:
1. Почему строка пустая?
std::string это контейнер, который выделяет память под строку. Когда вы делаете &mystr[0] вы получаете указатель на этот буфер (опустим скучные подробности). В вашем случае контейнер изначально пустой, по идее даже сам факт обращения по индексу внутрь такой строки — UB, но это нам знатоки стандарта подскажут.
Скорее всего имеет место оптимизация для хранения маленьких строк, поэтому там не скучный null указатель, а указатель на некий внутренний буфер. Поэтому вам удается записать вовнутрь немного текста. Скорее всего если вы запишите побольше, оно все-таки упадет.
Почему же не смотря на то что вы туда что-то смогли записать она все еще пустая? Строка хранит свой размер, а не вычисляет его каждый раз заново. Поэтому даже после модификации буфера и записи 0 — она все еще считает себя пустой.
3. Хочу писать на С!
Этот вариант сложнее, т.к. С ничего не знает про с++ обьекты, и памятью придется управлять самому. Обычно есть два подхода:
* как-то узнать нужный размер буфер и выделить его заранее
* выделить буфер фиксированного размера и молиться и передать размер в ф-цию
Часто совмещают оба подхода, типа:
Я опускаю скучные подробности по анализу кода ошибки.
Ниже идет сообщение которое я планировал писать изначально:
Вы явно плохо понимаете что вы пишите, для начала стоит почитать книжку для начинающих, типа Страуструпа, или еще что-то подобное. Тут периодически проскакивают хорошие варианты.
А потом, если остануться непонятные моменты — уже можно спрашивать в интернете.
Здравствуйте, indee, Вы писали:
W>>В функции test это требование нарушается и запись идёт за пределы этого диапазона, перезатирая чужие данные.
I>Что же делать?
Здравствуйте, saf_e, Вы писали:
_>Давайте попробуем пройтись по пунктах: _>1. Почему строка пустая?
_>std::string это контейнер, который выделяет память под строку. Когда вы делаете &mystr[0] вы получаете указатель на этот буфер (опустим скучные подробности). В вашем случае контейнер изначально пустой, по идее даже сам факт обращения по индексу внутрь такой строки — UB, но это нам знатоки стандарта подскажут. _>Скорее всего имеет место оптимизация для хранения маленьких строк, поэтому там не скучный null указатель, а указатель на некий внутренний буфер. Поэтому вам удается записать вовнутрь немного текста. Скорее всего если вы запишите побольше, оно все-таки упадет.
Это справедливо для вектора, и не совсем справедливо для std::string. Хотя чисто теоретически c_str() может отдельно выделять память под Z-terminated строку, скорее всего ноль в строке лежит всегда, и даже когда она пустая. Но да, small string optimization наверное тоже — иначе для пустой строки до первого вызова c_str() или data() память бы не выделялась.
И да, для строк, начиная с C++ 11, допустимо обращаться по индексу "pos == size()" —
If pos == size(), a reference to the character with value CharT() (the null character) is returned.
Здравствуйте, saf_e, Вы писали:
_>Здравствуйте, indee, Вы писали:
I>>Почему mystr пустая и длина = 0 (mystr.length())?
I>>Спасибо!
_>Это вам еще повезло что она просто пустая, при таком подходе обычно программа падает.
_>Давайте попробуем пройтись по пунктах: _>1. Почему строка пустая?
_>std::string это контейнер, который выделяет память под строку. Когда вы делаете &mystr[0] вы получаете указатель на этот буфер (опустим скучные подробности). В вашем случае контейнер изначально пустой, по идее даже сам факт обращения по индексу внутрь такой строки — UB, но это нам знатоки стандарта подскажут. _>Скорее всего имеет место оптимизация для хранения маленьких строк, поэтому там не скучный null указатель, а указатель на некий внутренний буфер. Поэтому вам удается записать вовнутрь немного текста. Скорее всего если вы запишите побольше, оно все-таки упадет. _>Почему же не смотря на то что вы туда что-то смогли записать она все еще пустая? Строка хранит свой размер, а не вычисляет его каждый раз заново. Поэтому даже после модификации буфера и записи 0 — она все еще считает себя пустой.
_>2. Что же делать? _>Писать на С++:
_>
_>3. Хочу писать на С! _>Этот вариант сложнее, т.к. С ничего не знает про с++ обьекты, и памятью придется управлять самому. Обычно есть два подхода: _> * как-то узнать нужный размер буфер и выделить его заранее _> * выделить буфер фиксированного размера и молиться и передать размер в ф-цию _>Часто совмещают оба подхода, типа: _>
_>Я опускаю скучные подробности по анализу кода ошибки.
_>Ниже идет сообщение которое я планировал писать изначально: _> _>Вы явно плохо понимаете что вы пишите, для начала стоит почитать книжку для начинающих, типа Страуструпа, или еще что-то подобное. Тут периодически проскакивают хорошие варианты. _>А потом, если остануться непонятные моменты — уже можно спрашивать в интернете. _>