C++ Builder
| Главная | Уроки | Статьи | FAQ | Форум | Downloads | Литература | Ссылки | RXLib | Диски |

 
Глупый вопрос про тип AnsiString
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++ как только объект становится не нужен (не используемые константные объекты он просто не создаёт smile.gif а 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;
Так ведь?


Так! Но лучше вот так smile.gif


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: длина имён — это просто потому что в неудобном текстовом окошке реплай набираем smile.gif Кстати, а почему второй вариант предпочтительней??? оч странно...

2Георгий: так я говорю. "с референс каунтером" — по-русски это "со счётчиком ссылок".
>>std::string реализован как умный указатель и даже в древнем
>>Watcom C++10.6
И программируя в нём я на всякий случай не доверял портированной под него stl, кстати smile.gif
Блин, если б AnsiString было частью stl, я ещё понимаю. Тогда бы разговор шёл об stl и кто как её у себя реализует. Но ведь Борланд лишь краем уха обмолвились, что мол, да, референс каунтер.
Кстати, stlport живёт в Билдере параллельно с AnsiString.
В этом топике мне, чесгря, хотелось чтобы ктото на этого зверя мне глаза до конца открыл. Что это, породия на std::string? или?.. Сейчас нет времени в этакие "мелочи" влезать. Но может кого припёрло или просто было интересно... хотя это уже почти флейм...
Treumer
Отправлено: 12.08.2005, 09:35


Станционный диспетчер

Группа: Участник
Сообщений: 92



QUOTE (Tertium @ 11/08/2005, 22:10)
2Treumer: длина имён — это просто потому что в неудобном текстовом окошке реплай набираем smile.gif Кстати, а почему второй вариант предпочтительней??? оч странно...

Вот это присвоение — лишее:
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;

Что называется найди десять отличий smile.gif
Rius
Отправлено: 12.08.2005, 15:57


Мастер участка

Группа: Участник
Сообщений: 321



Не, зашибись у вас способы вывода!!! biggrin.gif
А так нельзя? :
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



а пора бы smile.gif
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. С какой-то позиции концепция удобная, типа простой, но всёже оно как-то приятней явно методы звать, а не переменную. К тому ж еще в децком садике учат — не обращайтесь к данным класса, используйте интерфейс. Поэтому немного конечно глаз эти пропертя режут.

Только я думал уж можно отловить вызыв константных и неконстантных и соответственно вызывать геттера или сеттера.

Вернуться в Вопросы программирования в C++Builder