Здравствуйте, gid_vvp, Вы писали:
_>перечислите, на ваш взгляд, основные минусы STL _>принимаются только ответы с аргументацией
Строки из STL практически нигде не используются. Используются велосипеды или char*. Ни с тем ни с другим std::string нормально не сопрягается. Главным образом потому, что c_str() возвращает не внутренний буфер, а временный. Лишнее копирование никому не нужно.
Mazay wrote:
> Строки из STL практически нигде не используются. Используются велосипеды > или char*. Ни с тем ни с другим std::string нормально не сопрягается. > Главным образом потому, что c_str() возвращает не внутренний буфер, а > временный. Лишнее копирование никому не нужно.
На такое vector<char> есть.
Posted via RSDN NNTP Server 2.0
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Здравствуйте, kan_izh, Вы писали:
_>Mazay wrote:
>> Строки из STL практически нигде не используются. Используются велосипеды >> или char*. Ни с тем ни с другим std::string нормально не сопрягается. >> Главным образом потому, что c_str() возвращает не внутренний буфер, а >> временный. Лишнее копирование никому не нужно. _>На такое vector<char> есть.
Это не очевидно. Зачем тогда вообще этот std::string ?
Здравствуйте, Mazay, Вы писали:
M>Здравствуйте, gid_vvp, Вы писали:
_>>перечислите, на ваш взгляд, основные минусы STL _>>принимаются только ответы с аргументацией
M>Строки из STL практически нигде не используются. Используются велосипеды или char*. Ни с тем ни с другим std::string нормально не сопрягается. Главным образом потому, что c_str() возвращает не внутренний буфер, а временный. Лишнее копирование никому не нужно.
Строки не входят в STL, STL — это только контейнеры и алгоритмы.
Mazay wrote:
>> > Строки из STL практически нигде не используются. Используются велосипеды >> > или char*. Ни с тем ни с другим std::string нормально не сопрягается. >> > Главным образом потому, что c_str() возвращает не внутренний буфер, а >> > временный. Лишнее копирование никому не нужно. > _>На такое vector<char> есть. > Это не очевидно. Зачем тогда вообще этот std::string ?
На остальное. Не вседа и не вся программа состоит из взаимодействия с левыми компонентами char* (не const!), а с
велосипедами вообще ничего не поделаешь в общем случае.
Posted via RSDN NNTP Server 2.0
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Здравствуйте, Mazay, Вы писали:
M>Здравствуйте, kan_izh, Вы писали:
_>>Mazay wrote:
>>> Строки из STL практически нигде не используются. Используются велосипеды >>> или char*. Ни с тем ни с другим std::string нормально не сопрягается. >>> Главным образом потому, что c_str() возвращает не внутренний буфер, а >>> временный. Лишнее копирование никому не нужно. _>>На такое vector<char> есть.
M>Это не очевидно. Зачем тогда вообще этот std::string ?
Для всего остального
Хотя, конечно, следующий код не вызывает у меня энтузиазма
int len = some.GetTextLength();
std::vector<char> buffer(len);
some.GetText(&buffer[0], buffer.size());
std::string text(&buffer[0], buffer.size());
Здравствуйте, kan_izh, Вы писали:
>> _>На такое vector<char> есть. >> Это не очевидно. Зачем тогда вообще этот std::string ? _>На остальное. Не вседа и не вся программа состоит из взаимодействия с левыми компонентами char* (не const!), а с _>велосипедами вообще ничего не поделаешь в общем случае.
Ахха! Да пусть там хоть в одной строчке конвертация из char*, или wxString, или AnsiString в std::string происходит. Если это требует копирования это может дать тормоза. А мне этого не надо. К тому же не уверен что если сейчас эта строчка одна, то и завтра ещё где-нить надобность в конвертации не выплывет
Здравствуйте, Aera, Вы писали:
A>Хотя, конечно, следующий код не вызывает у меня энтузиазма A>
A> int len = some.GetTextLength();
A> std::vector<char> buffer(len);
A> some.GetText(&buffer[0], buffer.size());
A> std::string text(&buffer[0], buffer.size());
A>
Я от такого кода чешусь — физически такой penalty не могу переварить. Я ж потом два дня буду больным ходить,если такое придётся написать. Подумать только — ради использования библиотеки — гонять целые строки по памяти. Но самое главное что этим дело скорей всего не закончится и где то будет код типа:
A>
Здравствуйте, Mazay, Вы писали:
M>Здравствуйте, gid_vvp, Вы писали:
_>>перечислите, на ваш взгляд, основные минусы STL _>>принимаются только ответы с аргументацией
M>Строки из STL практически нигде не используются. Используются велосипеды или char*. Ни с тем ни с другим std::string нормально не сопрягается. Главным образом потому, что c_str() возвращает не внутренний буфер, а временный. Лишнее копирование никому не нужно.
Mazay wrote: > Строки из STL практически нигде не используются. Используются велосипеды > или char*. Ни с тем ни с другим std::string нормально не сопрягается. > Главным образом потому, что c_str() возвращает не внутренний буфер, а > временный.
В STL в VS 7/7.1/8 и GCCшной stdlib указатель возвращается на нормальный
буффер.
Здравствуйте, Mazay, Вы писали:
M>Здравствуйте, gid_vvp, Вы писали:
_>>перечислите, на ваш взгляд, основные минусы STL _>>принимаются только ответы с аргументацией
M>Строки из STL практически нигде не используются. Используются велосипеды или char*. Ни с тем ни с другим std::string нормально не сопрягается. Главным образом потому, что c_str() возвращает не внутренний буфер, а временный. Лишнее копирование никому не нужно.
ИМХО хорошим тоном считается немедленное копирование raw char* куда-нибудь при получении его через c_str. Иначе его хранение может сильно испортить настроение.
Mazay wrote: > A> some.SetText(text.c_str()); > A> > с ещё одним копированием
Нет тут копирования во всех реализациях STL которые я знаю. С чего оно
должно появится?
M>Строки из STL практически нигде не используются. Используются велосипеды или char*. Ни с тем ни с другим std::string нормально не сопрягается. Главным образом потому, что c_str() возвращает не внутренний буфер, а временный. Лишнее копирование никому не нужно.
std::string::c_str() возвращает указатель типа char const *, содержащий size() + 1 символов, представляющих строку и завершающихся '\0'.
Указатель действителен до ближайшего вызова non-const метода.
Вот имменно.
Пример я привёл для того чтобы показать что в принципе c_str() и begin() могут указывать на одну и ту же
память.
Независимо от того, возвращает c_str() указатель на тот же буффер что и begin()
или нет, std::string ничего никуда не копирует при вызове c_str() c_str() вызывается за константное
время.
Кстати std::string ничего не копирует во "временный" буфер также при операциях вставки и добавлении,
я вас уверяю.
И это НЕ хороший тон, когда результат c_str() копируется куда-то ещё.
Нужно пользоваться тем что он валиден, до вызова неконстантной функции.
А я как минимум года 4 использую std::string, std::vector и не могу нарадоваться.
Вообще-то нужно ещё поискать классы, которые также хорошо и продуманно спроектированы
как std::string и std::vector
3. c_str() ничего не копирует во временный буффер, а просто возвращает указатель на буффер.
const _Elem *c_str() const
{ // return pointer to null-terminated nonmutable arrayreturn (_Myptr());
}
const _Elem *_Myptr() const
{ // determine current pointer to buffer for nonmutable stringreturn (_BUF_SIZE <= _Myres ? _Bx._Ptr : _Bx._Buf);
}
В случае с vc7.1 приминяется оптимизация на маленьких строках оттуда и берёться _Bx._Buf
Собственно без этой оптимизации наверное и будет единственный случай когда c_str()!=&*begin()
std::string s;
s.c_str()//нету внутреннего буффера, поэтому &*begin()==0, а c_str() возвращает ""
4. Также все данные находяться в непрерывном массиве. Только увеличиваем память если нужно _Grow()
и копируем в конец
5. Также всё сплошным буффером, Увеличиваем, раздвигаем, копируем.
_Myt& insert(size_type _Off, const _Elem *_Ptr)
{ // insert [_Ptr, <null>) at _Offreturn (insert(_Off, _Ptr, _Traits::length(_Ptr)));
}
_Myt& insert(size_type _Off,
const _Elem *_Ptr, size_type _Count)
{ // insert [_Ptr, _Ptr + _Count) at _Offif (_Inside(_Ptr))
return (insert(_Off, *this,
_Ptr - _Myptr(), _Count)); // substringif (_Mysize < _Off)
_String_base::_Xran(); // _Off off endif (npos - _Mysize <= _Count)
_String_base::_Xlen(); // result too long
size_type _Num;
if (0 < _Count && _Grow(_Num = _Mysize + _Count))
{ // make room and insert new stuff
_Traits::move(_Myptr() + _Off + _Count,
_Myptr() + _Off, _Mysize - _Off); // empty out hole
_Traits::copy(_Myptr() + _Off, _Ptr, _Count); // fill hole
_Eos(_Num);
}
return (*this);
}
К сожалению у меня нет стандарта, и я не могу точно на него сослаться.
Но даже, если стандарт не запрещает, это не значит что реализация будет так делать.
Просто не зачем это делать
Ещё долго можно распинаться на тему того, как стоит использовать std::string, но наверное хватит
P.S. А вообще кто-нибудь видел вживую реализацию std::string и std::vector которые хранили бы данные не сплошным массивом?
Откуда такие мысли?
Здравствуйте, Cyberax, Вы писали:
C>Mazay wrote: >> A> some.SetText(text.c_str()); >> A> >> с ещё одним копированием C>Нет тут копирования во всех реализациях STL которые я знаю. С чего оно C>должно появится?
А если внутренний буфер не одним куском выделен? Doc выше написал что выделенный буфер может умереть. Так что надо сразу копировать строку в "вечный" буфер.
Шебеко Евгений wrote:
> Вот имменно. > Пример я привёл для того чтобы показать что в принципе c_str() и begin() > могут указывать на одну и ту же > память. > Независимо от того, возвращает c_str() указатель на тот же буффер что и > begin() > или нет, std::string ничего никуда не копирует при вызове c_str() > c_str() вызывается за константное > время.
Это в стандарте не обещано, а если на это полагаться, то получится implementation specific, т.е. поменяв версию stl на
что-нибудь другое, поведение может изменится и c_str будет создавать временную копию (например, если строка хранится по
кусочкам, или используется пул строк).
> Кстати std::string ничего не копирует во "временный" буфер также при > операциях вставки и добавлении, > я вас уверяю.
> И это НЕ хороший тон, когда результат c_str() копируется куда-то ещё. > Нужно пользоваться тем что он валиден, до вызова неконстантной функции.
Это да. На самом деле c_str() сделан лишь для совместимости с С-style строками, и им пользоваться нужно по минимуму.
Posted via RSDN NNTP Server 2.0
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
_>поведение может изменится и c_str будет создавать временную копию (например, если строка хранится по _>кусочкам, или используется пул строк).
А вы знаете хоть одну реализацию, которая так делает?
Действительно, просто интересно поглядеть на такую реализацию.
Я пользовался BC5.0,BC6.0,VC6,VC7,gcc2x,gcc3x ни одна из этих реализаций
такого не делает.
Mazay wrote: > C>Нет тут копирования во всех реализациях STL которые я знаю. С чего оно > C>должно появится? > А если внутренний буфер не одним куском выделен?
Ни разу такого не видел. В следующий Стандарт, кстати, добавят пункт о
том, что строка должна располагаться непрерывно в памяти.
Копирование в c_str может произойти если требуется добавить в строку
завершающий 0. Например, const_string от Максима Егорушкина позволяет
делать такое:
//В этой строчке, кстати, не происходит динамического
//распределения памяти - в строку записывается ссылка
//на константную строку.
const_string<char> str(boost::cref("Hello, world!"));
//В another попадает ссылка на родительскую строку и
//позиция подстроки. Копирования нет.
const_string<char> another=str.substr(1,2);
//О нет! Нужен завершающий '0'! Происходит копирование
//подстроки и добавление конечного нуля.
printf(another.c_str());
> Doc выше написал что выделенный буфер может умереть.
Нет. Он может умереть в случае вызова неконстантного метода.
> Так что надо сразу копировать строку в "вечный" буфер.
Зачем?
Здравствуйте, Cyberax, Вы писали:
>> А если внутренний буфер не одним куском выделен? C>Ни разу такого не видел. В следующий Стандарт, кстати, добавят пункт о C>том, что строка должна располагаться непрерывно в памяти.
Значит и Комитет признаёт, что отсутствие такого требования — ошибка.
>> Doc выше написал что выделенный буфер может умереть. C>Нет. Он может умереть в случае вызова неконстантного метода.
Вот именно. ИМХО на практике это означает "когда угодно", поскольку существует туча случаев, когда вызов неконстантного метода можэно незаметить.
>> Так что надо сразу копировать строку в "вечный" буфер. C>Зачем?
Затем, что буфер, возвращаемый c_str(), использовать опасно, ибо он может быть неявно совобожлён при вызове неконстантного метода строки.
Здравствуйте, Smal, Вы писали:
S>Здравствуйте, Aera, Вы писали:
A>>Строки не входят в STL, STL — это только контейнеры и алгоритмы.
S>Где это написано, что string не входит в STL?
Здравствуйте, kan_izh, Вы писали:
>> И это НЕ хороший тон, когда результат c_str() копируется куда-то ещё. >> Нужно пользоваться тем что он валиден, до вызова неконстантной функции. _>Это да. На самом деле c_str() сделан лишь для совместимости с С-style строками, и им пользоваться нужно по минимуму.
Хорошо, как тогда следует объявлять, скажем, параметры функции? foo(std::string const &)? Тогда CString, AnsiString, BicycleString и т. п. в пролете, здесь уже гарантированно лишнее копирование. Я еще могу согласиться с template <class It> R foo(It first, It last), но и этот вариант имеет проблемы: реализация обязательно в header'е, да и пресловутое code bloat.
Здравствуйте, Mazay, Вы писали:
C>>Нет. Он может умереть в случае вызова неконстантного метода. M>Вот именно. ИМХО на практике это означает "когда угодно", поскольку существует туча случаев, когда вызов неконстантного метода можэно незаметить.
Я фигею, дорогая редакция.
А как иначе ещё может вести себя std::string? Это ведь не класс-шаман, который знает обо всём, что творится в программе. Откуда ему знать, что там дальше программма будет делать с const char*?
Это то же самое, что недоумевать по поводу голого char* : я передал указатель другому экземпляру класса, сам позже поменял значение по это указателю и, в итоге, тот класс, которому я передал указатель по значению содержит уже другую информацию, а не ту, что я хотел.
Здравствуйте, Шебеко Евгений, Вы писали:
ШЕ>P.S. А вообще кто-нибудь видел вживую реализацию std::string и std::vector которые хранили бы данные не сплошным массивом? ШЕ>Откуда такие мысли?
Что касается std::vector, то последовательное хранение элементов гарантируется Стандартом.
А вот относительно std::string такой гарантии нет, оттуда и мысли. На мой взгляд, вполне разумные, т.к. использование особенностей реализации может сослужить плохую службу в будущем.
Здравствуйте, Mazay, Вы писали:
M>Я от такого кода чешусь — физически такой penalty не могу переварить. Я ж потом два дня буду больным ходить,если такое придётся написать. Подумать только — ради использования библиотеки — гонять целые строки по памяти. Но самое главное что этим дело скорей всего не закончится и где то будет код типа:
A>>
A>> some.SetText(text.c_str());
A>>
Пользуйся CString из MFC и будет тебе счастье
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Не надо искать серьезный источник, источник в таких вопросах может быть только один -- Стандарт.
ISO/IEC
14882 :
The C + + Standard Library provides an extensible framework, and contains components for: language support,
diagnostics, general utilities, strings, locales, containers, iterators, algorithms, numerics, and
input/output. The language support components are required by certain parts of the C + + language, such as
memory allocation (5.3.4, 5.3.5) and exception processing (clause 15).
Здравствуйте, Nose, Вы писали:
N>Здравствуйте, Roman Odaisky, Вы писали:
S>>>Где это написано, что string не входит в STL?
RO>>А где написано, что входит?
N>В стандарте.
В стандарт входят только семь контейнеров: vector, deque, list, set, multiset, map, multimap.
string не входит.
Здравствуйте, Nose, Вы писали:
N>Здравствуйте, Aera, Вы писали:
A>>Лень искать серьезный источник. Можно посмотреть здесть Стандартная_библиотека_шаблонов
N>Не надо искать серьезный источник, источник в таких вопросах может быть только один -- Стандарт.
N>ISO/IEC N>14882 :
N>The C + + Standard Library provides an extensible framework, and contains components for: language support,
Стандарт описывает стандартную библиотеку, а STL — "стандартная библиотека шаблонов", это нечто совсем другое. STL в стандарте вообще не упоминается, поскольку это историческое название библиотеки контейнеров и алгоритмов. Строки и потоки ввода вывода входят в стандартную библиотеку, но не входят в STL.
Здравствуйте, Nose, Вы писали:
N>ISO/IEC N>14882 :
N>The C + + Standard Library provides an extensible framework, and contains components for: language support, N>diagnostics, general utilities, strings, locales, containers, iterators, algorithms, numerics, and N>input/output. The language support components are required by certain parts of the C + + language, such as N>memory allocation (5.3.4, 5.3.5) and exception processing (clause 15).
Не путай C++ Standard Library и Standard Template Library.
— std::string входит в C++ Standard Library
— Standard Template Library входит в C++ Standard Library
— std::string не входит в Standard Template Library
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
It is always bad to give advices, but you will be never forgiven for a good one.
Oscar Wilde
Здравствуйте, KBH, Вы писали:
KBH>Здравствуйте, KBH, Вы писали:
KBH>>В стандарт входят только семь контейнеров: vector, deque, list, set, multiset, map, multimap. KBH>>string не входит.
KBH>Пардон, в STL, а не в стандарт.
Угу, разобрался... Это у меня смешение понятий произошло — C++ Standard Library и STL
Здравствуйте, Nose, Вы писали:
N>The C + + Standard Library provides an extensible framework, and contains components for: language support, N>diagnostics, general utilities, strings, locales, containers, iterators, algorithms, numerics, and N>input/output. The language support components are required by certain parts of the C + + language, such as N>memory allocation (5.3.4, 5.3.5) and exception processing (clause 15).
нда, пардон.
Это у меня смешение понятий произошло — C++ Standard Library и STL
KBH wrote: > В стандарт входят только семь контейнеров: vector, deque, list, set, > multiset, map, multimap. > string не входит.
В Стандарте нет разделения на STL и не-STL.
Nose wrote:
> KBH>>В стандарт входят только семь контейнеров: vector, deque, list, > set, multiset, map, multimap. > KBH>>string не входит. > KBH>Пардон, в STL, а не в стандарт. > Угу, разобрался... Это у меня смешение понятий произошло — C++ Standard
Чуваки буквоедством занимаются, не обращай внимания.
Posted via RSDN NNTP Server 2.0
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Здравствуйте, Mazay, Вы писали:
M>Здравствуйте, Cyberax, Вы писали:
>>> А если внутренний буфер не одним куском выделен? C>>Ни разу такого не видел. В следующий Стандарт, кстати, добавят пункт о C>>том, что строка должна располагаться непрерывно в памяти. M>Значит и Комитет признаёт, что отсутствие такого требования — ошибка.
>>> Doc выше написал что выделенный буфер может умереть. C>>Нет. Он может умереть в случае вызова неконстантного метода. M>Вот именно. ИМХО на практике это означает "когда угодно", поскольку существует туча случаев, когда вызов неконстантного метода можэно незаметить.
>>> Так что надо сразу копировать строку в "вечный" буфер. C>>Зачем? M>Затем, что буфер, возвращаемый c_str(), использовать опасно, ибо он может быть неявно совобожлён при вызове неконстантного метода строки.
а ты как хотел??? вызвали неконстантный метод -> строка изменилась -> возможная переаллокация памяти -> закономерность невалидности результата предыдущего выщова c_str!
да что вы паритесь? главное, что результат c_str ничего не копирует (иначе кто должен это освобождать?) и валиден до следующей модификации строки. А этого времени, я думаю, будет достаточно, чтобы передать raw ptr в (WIN/LINUX)API функции и забыть.
Здравствуйте, Константин Л., Вы писали:
КЛ>ИМХО хорошим тоном считается немедленное копирование raw char* куда-нибудь при получении его через c_str. Иначе его хранение может сильно испортить настроение.
Ну так ведь, знаете, и указатели на элементы вектора тоже не стоит хранить... Потому что при первом же reserve они инвалидируются.
А для строк инвалидирование происходит и при более мягких условиях: при любом факте изменения. И это осмысленно.
Строка — это, в первую очередь, текстовое значение — и только потом контейнер символов. Это касается как std::string, так и CString, и AnsiString, и всяких велосипедов.
КЛ>>ИМХО хорошим тоном считается немедленное копирование raw char* куда-нибудь при получении его через c_str. Иначе его хранение может сильно испортить настроение.
К>Ну так ведь, знаете, и указатели на элементы вектора тоже не стоит хранить... Потому что при первом же reserve они инвалидируются. К>А для строк инвалидирование происходит и при более мягких условиях: при любом факте изменения. И это осмысленно. К>Строка — это, в первую очередь, текстовое значение — и только потом контейнер символов.
Такой подход и привел к тому, что std::string невозможно нормально с API использовать... Имхо, строка должна быть _и_ текстом _и_ контейнером, причем довольно специфическим. Наиболее приятно работать, как ни странно, с CString, хотя он спроектирован ну совсем не по "правилам" — ни вам тут итераторов, ни алгоритмов, ни внешних функций, все на индексах. Ан нет, нормально и вполне удобно получается. В общем, мое мнение, что std::string в большинстве практических случаев — анюзабл. Сам по себе — он вполне самодостаточен. Но как только пытаешься его использовать при взаимодействии с апи или другим нативным кодом — все, швах. По-крайней мере, во всех проектах, где участвовал я, std:string либо использовался как временное хранилище для интерфейса с другими библиотеками, либо его не было вообще.
Здравствуйте, Кодт, Вы писали:
К>Здравствуйте, Константин Л., Вы писали:
КЛ>>ИМХО хорошим тоном считается немедленное копирование raw char* куда-нибудь при получении его через c_str. Иначе его хранение может сильно испортить настроение.
К>Ну так ведь, знаете, и указатели на элементы вектора тоже не стоит хранить... Потому что при первом же reserve они инвалидируются.
ну я и не храню.
К>А для строк инвалидирование происходит и при более мягких условиях: при любом факте изменения. И это осмысленно.
exactly
К>Строка — это, в первую очередь, текстовое значение — и только потом контейнер символов. Это касается как std::string, так и CString, и AnsiString, и всяких велосипедов.
к сожалению, в с/с++ это, в первую очередь, указатель на непрерывную область памяти, из-за чего все проблемы
Роман! А что не так?
Как раз вот такие фокусы в MFCишной строке хорошо обустроены.
И вообще, строка как раз в MFC ИМХО не такая уж и плохая
Во всяком случае в не слишком древнем MFC
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
1. What is the STL (Standard Template Library)?
A. The STL is a data structures or container class library that has
been adopted into the language. It consists of three major components:
Containers or data structures
Iterators
Algorithms
Containers include such things as vectors, lists, queues, priority
queues, stacks, maps, and sets. In STL, containers (data structures)
are templatized.
...
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
Здравствуйте, Cyberax, Вы писали:
C>В следующий Стандарт, кстати, добавят пункт о том, что строка должна располагаться непрерывно в памяти.
А нет ли ссылочки? А то в драфте (DTR 19768) не нашел
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth