Tertium |
Отправлено: 03.08.2005, 15:56 |
|
Машинист паровоза
Группа: Почетный участник
Сообщений: 192
|
у меня часто встерчаются строчки вроде:
CODE |
MessageBox(MainWnd->Handle,(AnsiString().sprintf("Код события пришёл: %d",m_buffer[i])).c_str(), "",0);
|
Периодически вываливается прога на таких строчках. А если сделать:
CODE |
char tmp[255]={0};
sprintf(tmp,"Код события пришёл: %d",m_buffer[i]);
MessageBox(MainWnd->Handle,tmp, "",0);
|
всё вроде работает.
Может дело в конструкции
CODE |
AnsiString().sprintf(...)
|
?
Вообще если бы AnsiString был обычным сёвым классом, вопросов бы не было. Где-то загажена память, вот он и бесится. Но вот только это же паскальный класс. Ктонть на такое нарывался? Ктонть вообще имел какиенть проблемы с AnsiString?
|
|
Rius |
Отправлено: 03.08.2005, 17:05 |
|
Мастер участка
Группа: Участник
Сообщений: 321
|
Все нормально работает, только мудрить не надо...
CODE | Application->MessageBox(
AnsiString( "Код события пришёл: " + AnsiString(m_buffer[i]) ).c_str(),
"заголовок",
MB_OK); |
|
|
Tertium |
Отправлено: 03.08.2005, 17:11 |
|
Машинист паровоза
Группа: Почетный участник
Сообщений: 192
|
мудрить? это блин тебе с одной переменной хорошо говорить, а если на лету создаётся sql-запрос, где их 38? Да, кстати, если в твою форму переписать — действительно работает. Но вот вопрос, на кой они сделали тогда метод sprintf, если он течёт?
|
|
Георгий |
Отправлено: 03.08.2005, 21:37 |
|
Почетный железнодорожник
Группа: Модератор
Сообщений: 874
|
QUOTE (Tertium @ 03/08/2005, 18:11) | мудрить? это блин тебе с одной переменной хорошо говорить, а если на лету создаётся sql-запрос, где их 38? Да, кстати, если в твою форму переписать — действительно работает. Но вот вопрос, на кой они сделали тогда метод sprintf, если он течёт? |
он не течёт.
разобрать твою конструкцию? запросто.
CODE | MessageBox(MainWnd->Handle,(AnsiString().sprintf("Код события пришёл: %d",m_buffer[i])).c_str(), "",0); |
1. создаётся анонимный объект класса AnsiString (для простоты изложения назовём его A)
2. у A вызывается метод sprintf который возвращает ещё один временный анонимный объект класса AnsiString (пусть будет B )
3. у B вызывается константный метод c_str(), который возвращает указатель на константную строку.
4. т.к. объекты A и B больше не нужны, то они грохаются и в функцию MessageBox передаётся только указатель полученный на шаге 3
результат очевиден — указатель указывает на то место где раньше была строка, а сейчас находится свободная динамическая память со всеми вытекающими последствиями.
PS. хоть С++ и позволяет в одну строку писать выражения вызова + формирования + преобразования, но лучше так не писать
PPS. разные компиляторы по разному такие вещи делают — например sun pro грохает временные объекты только при выходе из области видимости (после закрывающей фигурной скобки), а Watcom C++ как только объект становится не нужен (не используемые константные объекты он просто не создаёт а BCB, если не изменяет склероз, грохнет только B, а A будет жить до окончания работы функции, но это сути не меняет.
Отредактировано Георгий — 03/08/2005, 22:52 |
|
Tertium |
Отправлено: 03.08.2005, 21:56 |
|
Машинист паровоза
Группа: Почетный участник
Сообщений: 192
|
То есть получается что спринтф не только меняет созданный AnsiString() автоматич. объект А, но и возвращает ещё один? Мне казалось что он возвращает ссылку на А... Ну по борландовской справке это не поймёшь.
Ну ладно.
Но ведь вариант с c_str() (1 occurence) в приложении появился только сегодня, а вылетало и раньше.
А если вот так:
CODE |
Label1->Caption=AnsiString().sprintf("Код события пришёл: %d",m_buffer[i]);
|
?
Ну и получает Caption автоматический объект от sprintf. И что? Здесь-то что не так?
И ещё вопрос. Почему во всём VCL объекты AnsiString передаются не по указателю? Может это реализовано внутри как "хитрый указатель"? Или такой у борланда стиль:)?
Отредактировано Tertium — 03/08/2005, 22:09
|
|
Guest |
Отправлено: 03.08.2005, 22:30 |
|
Не зарегистрирован
|
CODE | AnsiString().sprintf() |
Какая то это кривая конструкция.
не проще ли просто уже иметь эту переменную ?
и делайте с ней что хотите:
CODE |
AnsiString s;
Label1->Caption = s.sprintf("Код события пришёл: %d",m_buffer[i]); |
или
[CODE]
void __fastcall TForm1::Button1Click(TObject *Sender)
{
int m=10, b=125, c=54, d=11;
AnsiString s;
s = s.sprintf("Код события: %d %d %d %d", m,b,c,d);
Label1->Caption = s;
} |
|
Tertium |
Отправлено: 03.08.2005, 22:48 |
|
Машинист паровоза
Группа: Почетный участник
Сообщений: 192
|
да какая разница, объект-то автоматический и так и так.
И всёравно, если продолжить логику предыдущих постов, получается, что Label1->Caption получает объект уже не A, а Б.
А вот эта строка вообще смех:
s = s.sprintf("Код события: %d %d %d %d", m,b,c,d);
|
|
Георгий |
Отправлено: 04.08.2005, 07:31 |
|
Почетный железнодорожник
Группа: Модератор
Сообщений: 874
|
да. он автоматический (класс памяти auto) но уже не анонимный и будет убит только после выходи из области видимости. т.е. на время работы всех функций внутри области видимости он и всё возвращённое его методами будет достоверным. |
|
Tertium |
Отправлено: 04.08.2005, 13:04 |
|
Машинист паровоза
Группа: Почетный участник
Сообщений: 192
|
короче, ясно. Лучше делать так.
AnsiString s;
Label->Caption=s.sprintf("бла бла бла %d", int_value);
и мне будет щастье.
Спасибо за наставления:)
А вот в случае:
AnsiString s;
s = s.sprintf("Код события: %d %d %d %d", m,b,c,d);
Label1->Caption = s;
достаточно:
AnsiString s;
s.sprintf("Код события: %d %d %d %d", m,b,c,d);
Label1->Caption = s;
Так ведь?
Отредактировано Tertium — 04/08/2005, 13:06
|
|
Tertium |
Отправлено: 11.08.2005, 15:39 |
|
Машинист паровоза
Группа: Почетный участник
Сообщений: 192
|
...тут ещё выяснилось, что в AnsiString реализован один из видов умного указателя — с референс каунтером, интересно, чем это чревато, и почему так мало об этом у Борланда? Чётко видна попытка сделать строку прозрачной в использовании, подобно паксалевскому string'у, как будто это часть языка. Но они должны были описать весь подводный "сад камней"! Чего, конечно, они никогда не делали...
|
|
Treumer |
Отправлено: 11.08.2005, 16:12 |
|
Станционный диспетчер
Группа: Участник
Сообщений: 92
|
QUOTE (Tertium @ 04/08/2005, 13:04) | AnsiString s;
s.sprintf("Код события: %d %d %d %d", m,b,c,d);
Label1->Caption = s;
Так ведь? |
Так! Но лучше вот так
CODE |
AnsiString sEventsCode;
sEventsCode.sprintf("Код события: %d %d %d %d", m,b,c,d);
Label1->Caption = sEventsCode;
|
И еще один совет: не экономьте на длине имён переменных и на количестве переменных тоже уже давно смысла экономить нет.
|
|
Георгий |
Отправлено: 11.08.2005, 21:26 |
|
Почетный железнодорожник
Группа: Модератор
Сообщений: 874
|
QUOTE (Tertium @ 11/08/2005, 16:39) | ...тут ещё выяснилось, что в AnsiString реализован один из видов умного указателя — с референс каунтером, интересно, чем это чревато, и почему так мало об этом у Борланда? Чётко видна попытка сделать строку прозрачной в использовании, подобно паксалевскому string'у, как будто это часть языка. Но они должны были описать весь подводный "сад камней"! Чего, конечно, они никогда не делали... |
и std::string реализован как умный указатель и даже в древнем Watcom C++10.6 (95-96 год выпуска) класс String сделан как умный указатель (кстати, со счётчиком ссылок) |
|
Tertium |
Отправлено: 11.08.2005, 22:10 |
|
Машинист паровоза
Группа: Почетный участник
Сообщений: 192
|
2Treumer: длина имён — это просто потому что в неудобном текстовом окошке реплай набираем Кстати, а почему второй вариант предпочтительней??? оч странно...
2Георгий: так я говорю. "с референс каунтером" — по-русски это "со счётчиком ссылок".
>>std::string реализован как умный указатель и даже в древнем
>>Watcom C++10.6
И программируя в нём я на всякий случай не доверял портированной под него stl, кстати
Блин, если б AnsiString было частью stl, я ещё понимаю. Тогда бы разговор шёл об stl и кто как её у себя реализует. Но ведь Борланд лишь краем уха обмолвились, что мол, да, референс каунтер.
Кстати, stlport живёт в Билдере параллельно с AnsiString.
В этом топике мне, чесгря, хотелось чтобы ктото на этого зверя мне глаза до конца открыл. Что это, породия на std::string? или?.. Сейчас нет времени в этакие "мелочи" влезать. Но может кого припёрло или просто было интересно... хотя это уже почти флейм...
|
|
Treumer |
Отправлено: 12.08.2005, 09:35 |
|
Станционный диспетчер
Группа: Участник
Сообщений: 92
|
QUOTE (Tertium @ 11/08/2005, 22:10) | 2Treumer: длина имён — это просто потому что в неудобном текстовом окошке реплай набираем Кстати, а почему второй вариант предпочтительней??? оч странно...
|
Вот это присвоение — лишее:
Str = Str.sprintf("Код события: %d %d %d %d", m,b,c,d);
Но еще лучше делать вот так:
Str.printf("Код события: %d %d %d %d", m,b,c,d);
|
|
Tertium |
Отправлено: 12.08.2005, 13:01 |
|
Машинист паровоза
Группа: Почетный участник
Сообщений: 192
|
Treumer: не, я о том реплае где мой код:
QUOTE | AnsiString s;
s.sprintf("Код события: %d %d %d %d", m,b,c,d);
Label1->Caption = s; |
и твой:
QUOTE | Но лучше вот так
AnsiString sEventsCode;
sEventsCode.sprintf("Код события: %d %d %d %d", m,b,c,d);
Label1->Caption = sEventsCode; |
Что называется найди десять отличий
|
|
Rius |
Отправлено: 12.08.2005, 15:57 |
|
Мастер участка
Группа: Участник
Сообщений: 321
|
Не, зашибись у вас способы вывода!!!
А так нельзя? :
CODE | int x=15165;
double g = 1.2154;
AnsiString str = "kghuidfhgirf";
Caption = Format("целое %d, с точкой %.5f, строка %s", ARRAYOFCONST((x, g, str)));
|
да,да, но не все еще на __int64 перешли...
Отредактировано Rius — 12/08/2005, 21:40
|
|
Tertium |
Отправлено: 12.08.2005, 16:12 |
|
Машинист паровоза
Группа: Почетный участник
Сообщений: 192
|
полаконичней выглядит... вот только он __int64 напрямую не знает, надо изворачиваться, кастить к варианту...
короче лучше sprintf'a видимо способа нет:
AnsiString s.sprintf("%Ld+%Ld=%Ld", i64val1,i64val2,i64val1+i64val2);
Label14->Caption=s;
Отредактировано Tertium — 12/08/2005, 17:49
|
|
Tertium |
Отправлено: 14.08.2005, 03:33 |
|
Машинист паровоза
Группа: Почетный участник
Сообщений: 192
|
а пора бы
|
|
Tertium |
Отправлено: 16.08.2005, 14:49 |
|
Машинист паровоза
Группа: Почетный участник
Сообщений: 192
|
до сих пор для меня загадка, почему:
AnsiString s;
s.sprintf("%d",i);
Label->Caption=s;
работает, а после
Label->Caption.s.sprintf("%d",i);
лабел пуст ???
|
|
Guest |
Отправлено: 16.08.2005, 16:10 |
|
Не зарегистрирован
|
Caption это проперть. |
|
Tertium |
Отправлено: 16.08.2005, 16:12 |
|
Машинист паровоза
Группа: Почетный участник
Сообщений: 192
|
ясен пень, но как проперть он имеет сеттера и геттера. получается в данном случае неявно вызывается геттер?.. то есть у пропертя как такового мона вызывать тока константные методы? А чо тада компилёр не матерится?
Отредактировано Tertium — 16/08/2005, 17:25
|
|
Георгий |
Отправлено: 16.08.2005, 22:56 |
|
Почетный железнодорожник
Группа: Модератор
Сообщений: 874
|
потому что проперть — придумка борланда и в С++ она пришла из дельфёвой ВЦЛ. ну ломало мужиков из борланда всю библиотеку переделывать, вот и сделали простенькую надстройку над транслятором.
PS. никого пребывающего в жутком восторге не видел от этих пропертей. всем либо пофиг, либо воспринимают, как данность. |
|
Tertium |
Отправлено: 16.08.2005, 23:11 |
|
Машинист паровоза
Группа: Почетный участник
Сообщений: 192
|
не токмо борланда это придумка. есть в менеджед с++ у мелкософта. Пишешь в классе get_myvar() и set_myvar(), а вызываешь через myvar. С какой-то позиции концепция удобная, типа простой, но всёже оно как-то приятней явно методы звать, а не переменную. К тому ж еще в децком садике учат — не обращайтесь к данным класса, используйте интерфейс. Поэтому немного конечно глаз эти пропертя режут.
Только я думал уж можно отловить вызыв константных и неконстантных и соответственно вызывать геттера или сеттера.
|
|