Речь идет о методах std::string...
Вот цитата из Страуструпа:
"Преобразование в С-строку может быть обеспечено оператором operator const char*(), а не c_str(). Это обеспечило бы удобство неявного преобразования, но ценой всякого рода сюрпризов в тех случаях, когда такого преобразования не ожидалось."
Угу, понятно — неявные преобразования на то и неявные, чтобы иногда происходить неожиданно и неявно :) Из-за чего с ними нужно проявлять внимательность, это понятно. В std::string не включен оператор неявного пеобразования в const char*, вместо этого — const char* c_str() const;
Внимание, вопрос!
Какой хороший (простой и очевидный) пример показал бы глубину грехопадения тех, кто склонен считать, что std::string::operator const char*() — это хорошо :)
С уважением,
Сергей
Re: Почему нет std::string::operator const char*()
Здравствуйте Brother, Вы писали:
B>Внимание, вопрос! B>Какой хороший (простой и очевидный) пример показал бы глубину грехопадения тех, кто склонен считать, что std::string::operator const char*() — это хорошо
П.Халперн."Стандартная библиотека С++ на примерах":
Весь вопрос в том, кто потом будет освобождать память.
вариант 1. Мы сами, ручками. Смотрим что из этого получится:
extern void f(const char*);
std:string s("hello world");
f(s); // f() принимает временный, неименованый указатель - > мы не сможем освободить память по этому адресу
вариант 2. Память будет очищать сам string
extern void f(const char*);
extern std:string g();
const char* p = g(); // !! std:string возвращаемый g()
// сохраняется во временной переменной string
f(p); // большой облом ! после выхода за строку 3
// временная переменная string уничтожается
// и очищает память, на которую указывает p.
// Что же мы передали в f()?
Re[2]: Почему нет std::string::operator const char*()
O$>Весь вопрос в том, кто потом будет освобождать память.
{skip}
А что кардинально изменится, если в этих двух примерах явно написать c_str()?
По-моему, зря они не включили этот оператор. Как будто в c++ мало других мест (даже в STL), где можно совершить ошибку (перепутать begin() и end(), например).
Успехов,
Виталий.
Re[3]: Почему нет std::string::operator const char*()
Здравствуйте retalik, Вы писали:
R>Здравствуйте Odi$$ey, Вы писали:
O$>>Весь вопрос в том, кто потом будет освобождать память.
R>{skip}
R>А что кардинально изменится, если в этих двух примерах явно написать c_str()?
в смысле результата — ничего. В смысле анализа кода на предмет того, а что же собственно происходит — коду добавится прозрачности, все-так неявное преобразование оно и есть неявное, и если текста не три строки, как в примере, то пялиться в него можно было бы довольно долго.
R>По-моему, зря они не включили этот оператор. Как будто в c++ мало других мест (даже в STL), где можно совершить ошибку (перепутать begin() и end(), например).
ну этож не причина добавить таких мест еще и побольше, побольше
Re[2]: Почему нет std::string::operator const char*()
O$>Весь вопрос в том, кто потом будет освобождать память.
O$>вариант 1. Мы сами, ручками. Смотрим что из этого получится:
Что-то тут не так...
O$>extern void f(const char*);
O$>std:string s("hello world");
O$>f(s); // f() принимает временный, неименованый указатель - > мы не сможем освободить память по этому адресу
А с какой мы должны освобождать память? Память освободится в деструкторе std:string s. Или я чего-то не понимаю?
O$>extern void f(const char*);
O$>extern std:string g();
O$>const char* p = g(); // !! std:string возвращаемый g()
O$> // сохраняется во временной переменной string
O$>f(p); // большой облом ! после выхода за строку 3
O$> // временная переменная string уничтожается
O$> // и очищает память, на которую указывает p.
O$> // Что же мы передали в f()?
строка, возвращаемая g() с равной вероятностью может умереть как до вызова f(p), так и после — это как уж разработчикам компилятора захочется.
Показан пример как не надо программировать.
Есть у меня эта "Стандартная библиотека С++ на примерах". Не в восторге. Плохой перевод, примитивные примеры. Полезность книги — нулевая :-(
Касательно первоначального вопроса пример могу привести такой:
std::string s("bla-bla-bla");
s += '\0';
s += "one more string";
std::cout << s;
С std::string::operator const char*() было бы не ясно — что выводить — то ли С-шную строку до символа '\0', то ли С++-ную целиком.
_____________________
С уважением,
Stanislav V. Zudin
Re[3]: Почему нет std::string::operator const char*()
Здравствуйте Stanislav V. Zudin, Вы писали:
SVZ>А с какой мы должны освобождать память? Память освободится в деструкторе std:string s. Или я чего-то не понимаю?
если у нас одна и таже область памяти используется и через std:string и через const char* p, то в принципе возможны два варианта освобождения этой памяти, вот эти два варианта и рассмотрены.
SVZ>строка, возвращаемая g() с равной вероятностью может умереть как до вызова f(p), так и после — это как уж разработчикам компилятора захочется.
это сути дела не меняет, только усугубляет, прошу прощения за тавтологию
SVZ>Показан пример как не надо программировать.
а никто и не просил пример хорошего стиля
SVZ>Есть у меня эта "Стандартная библиотека С++ на примерах". Не в восторге. Плохой перевод, примитивные примеры. Полезность книги — нулевая
не согласен, но не важно. А какая есть хорошая книга по STL на русском?
Re[4]: Почему нет std::string::operator const char*()
От:
Аноним
Дата:
30.11.01 07:43
Оценка:
Здравствуйте Odi$$ey, Вы писали:
O$>не согласен, но не важно. А какая есть хорошая книга по STL на русском?
Увы, других книг по STLю вообще не видел. Ни на русском, ни на аглицком. :( Стандарт и Страуструп не считаются.
Re[3]: Почему нет std::string::operator const char*()
Здравствуйте retalik, Вы писали:
R>Здравствуйте Odi$$ey, Вы писали:
O$>>Весь вопрос в том, кто потом будет освобождать память.
R>{skip}
R>А что кардинально изменится, если в этих двух примерах явно написать c_str()?
Изменится то, что тебе придется явно написать вызов этого метода. Явный вызов метода означает, что ты отдаешь себе отчет в том, что делаешь. Оператор приведения типа имеет свойство вызываться компиляторм неявно, что может привести к его вызову в ситуациях, когда ты этого не хотел и не ожидал. Логика тут примерно та же, что и в ключевом слове 'explicit' при объявлении конверсионного конструктора — подавить потенциално опасные неявные действия.
Еще одна причина, по которой 'c_str' не сделана в виде оператора приведения типа, заключается в том, что за этим методом может скрываться нетривиальная операция. Объекты класса 'std::string' хранят последовательности, которые в общем случае не являются null-теминаторными. Длина хранимой последовательности хранится отдельно и наличие терминаторного символа на конце хранимой поледовательности не требуется. (Более того, хранимая последовательность может содержать символы, которые ты считаешь терминаторными, в середине.) Это означает, что вызов метода 'c_str' в общем случае может выливаться в нетривиальную операцию, заключающуюся в копировании хранимой последовательности в новый буфер и с добавлением null-терминатора в конце. Например, стандарт языка говорит, что вызов 'c_str' инвалилирует все указатели, ссылки и итераторы, связанные с хранимой в 'std::string' последовательностью. Я думаю, многие согласятся, что использовать любые потенциально тяжелые действия в реализации оператора приведения типа — не самая лучшая идея, все по той самой причине, что оператор приведения типа вызывается неявно.
Многие реализации, конечно, будут "заранее" хранить последовательность в null-терминаторном виде и реализация 'c_str' в них будет тривиальной. Но стандартом языка этого не требуется.
Best regards,
Андрей Тарасевич
Re[5]: Почему нет std::string::operator const char*()
Здравствуйте Аноним, Вы писали:
А>Здравствуйте Odi$$ey, Вы писали:
O$>>не согласен, но не важно. А какая есть хорошая книга по STL на русском? А>Увы, других книг по STLю вообще не видел. Ни на русском, ни на аглицком. Стандарт и Страуструп не считаются.
А Леен Аммераль? На русском, и стиль писания книг и кода у него явно поменялся со времен его четырехтомника по графике, так что его книгу по STL читать одно удовольствие.
Re[6]: Почему нет std::string::operator const char*()
Здравствуйте Юнусов Булат, Вы писали:
ЮБ>А Леен Аммераль? На русском, и стиль писания книг и кода у него явно поменялся со времен его четырехтомника по графике, так что его книгу по STL читать одно удовольствие.
А поподробнее? Как называется, где и когда издана?
_____________________
С уважением,
Stanislav V. Zudin
Re[7]: Почему нет std::string::operator const char*()
Здравствуйте Stanislav V. Zudin, Вы писали:
SVZ>Здравствуйте Юнусов Булат, Вы писали:
ЮБ>>А Леен Аммераль? На русском, и стиль писания книг и кода у него явно поменялся со времен его четырехтомника по графике, так что его книгу по STL читать одно удовольствие. SVZ>А поподробнее? Как называется, где и когда издана?
Леен Аммерааль "STL для программистов на С++" ДМК, Москва, 1999
В нашем ascSrting сделано именно так как говорил retalik и что характерно ни одной проблемы за 3 года.
Проблема явно высосана из пальца. Мы при работе всегда подразумеваем, что памятью может управлять только хелпер... и никаких проблем. А общая логика работы похожа на работу с указателями на COM-интерфейс.
Работать же на порядок проще.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[5]: Почему нет std::string::operator const char*()
Здравствуйте VladD2, Вы писали:
VD>Проблема явно высосана из пальца. Мы при работе всегда подразумеваем, что памятью может управлять только хелпер... и никаких проблем.
однако, сколько человек, кроме разаработчиков применяют ascString? как там говорил лучший друг советских детей — "нет человека, нет и проблемы" ?
Re[5]: Почему нет std::string::operator const char*()
Здравствуйте VladD2, Вы писали:
VD>В нашем ascSrting сделано именно так как говорил retalik и что характерно ни одной проблемы за 3 года.
Это хорошо. Пожелаем всем нам хорошего кода!
VD>Проблема явно высосана из пальца. Мы при работе всегда подразумеваем, что памятью может управлять только хелпер... и никаких проблем. А общая логика работы похожа на работу с указателями на COM-интерфейс.
Да, наверное, не так страшен черт. Хотя и в комитете по стандартизации тоже не дураки сидят
Пока шла дискуссия, вот какой пример ошибки (взят почти из жизни) я нашел в оправдание Страуструпа со товарищи
LPCTSTR GetString()
{
CString str = "The stuff that sucks";
return str;
}
На первый взгляд "все чинно-блааронно", но при внимательном рассмотрении все становится на свои места — str является локальной переменной, при возвращении return str; экземпляр CString неявно приводится к указателю на строку (на внутренний буфер!) и тут же уничтожается, буфер освобождается, и по возвращении из функции имеем в руках указатель на занятую кем-то другим память. Грустно.
Естественно, если думать, что пишешь то такие ошибки не возникают, однако источник ошибок, по-моему, все же существует.
Ваше мнение?