Russian Qt Forum
Апрель 18, 2024, 01:09 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: QString::toAscii()  (Прочитано 8343 раз)
xk
Гость
« : Октябрь 08, 2006, 08:08 »

Возможно вопрос даже не по Qt, а по С++ в целом.

Код:

class CServer
{
public:
  QString getHost() const { return m_host; }
private:
  QString m_host;
};


Вот такой код работает нормально:
Код:

QByteArray tmp = serv.getHost().toAscii();
const char* target = tmp.data();


А вот при таком коде target указыввает на какой-то мусор:
Код:

QString tmp = serv.getHost();
const char* target = tmp.toAscii().data();


serv передается в ф-ию по константной ссылке.
Объясните плиз в 2-х словах почему так  :?:
Записан
Dendy
Гость
« Ответ #1 : Октябрь 08, 2006, 09:46 »

Вопрос уже когда-то обсуждался.

Суть в том, что в отличии от Qt3 - в Qt4 екземпляр QString не может хранить в себе кодированную копию строки, например, в ASCII формате. И правильно делает.

Метод toAscii() возвращает QByteArray, копию временно создаваемой переменной для с-строки. Естественно, если не сохранить ету копию - она сразу же удалится.

У QByteArray метод data() или constData() - ацессорьІ к области данньІх в самом QByteArray. Пока живёт его екземпляр, ети возвращённьІе указатели валидньІ и ими можно пользоваться.

При вьІходе из QString::toAscii() убивается из стека возвращённьІй им QByteArray, и, соответственно, копия указателя, полученного из data() - теперь указьІвает на мусор.

ВьІходов два:

1. Более правильньІй - пользоваться Qt копиями с-строк, то-бишь QByteArray:
Код:
QByteArray ascii_string = get_some_string().toAscii();
do_something_with_c_string( ascii_string.data() );
do_anything_else_with_c_string( ascii_string.data() );

Конвертация в ASCII здесь произошла один раз.

2. Подставлять в метод с-строку, полученную непосредственно из методов конвертации:
Код:
QString tmp = get_some_string();
do_something_with_c_string( tmp.toAscii().data() );

В етом случае указатель, переданньІй в метод do_something_with_c_string будет оставаться валидньІм до его завершения, так как временньІй екземпляр QByteArray остаётся жить в стеке и будет уничтожен сразу же при віходе из метода do_something_with_c_string.

Для наглядности ещё пример:

Код:
QString tmp = get_some_string();
char * c_string;
do_something_with_c_string( c_string = tmp.toAscii().data() );
// c_string is not valid now
do_anything_else_with_c_string( c_string );


ВьІзов первого метода проходит нормально.
ВьІзов второго - краш, так как в c_string теперь мусор.

P.S. Не пользуйтесь лишний раз QByteArray::data(), если вам действительно не нужно менять данньІе. Пользуйтесь QByteArray::constData(). Иначе скрьІтьІе общие данньІе будут разделеньІ и вьІ ни за что получите удар по процессору и памяти.
Записан
xk
Гость
« Ответ #2 : Октябрь 08, 2006, 10:39 »

Большое спасибо !
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.131 секунд. Запросов: 20.