Russian Qt Forum

Qt => Общие вопросы => Тема начата: fynjy от Май 17, 2009, 01:17



Название: Инициализация строк.
Отправлено: fynjy от Май 17, 2009, 01:17
Вопрос существует ли какой либо стандартный способ инициализации строк для QString кроме
Код:
QString str("bla bla bla");
в библиотеке QT? Меня интересуют макросы типа:
Код:
#define _L8(aString) QString::fromUtf8(aString, sizeof(aString) - 1)
#define _L16(aString) QString::fromWCharArray(L##aString, sizeof(L##aString) / 4 - 1)
Эти макросы мне нужны для того чтобы замерять длину строк на этапе компиляции, а не в рантайме как (предположительно происходит) в первом куске кода.

Спасибо.

PS. Насколько я понял в QT QString это единственный класс отвечающий за строки?


Название: Re: Инициализация строк.
Отправлено: Авварон от Май 17, 2009, 01:30
а поподробней можно узнать, что ты хочешь сделать? эти макросы я так понял для преобразования char* в QString и они ничего не замеряют


Название: Re: Инициализация строк.
Отправлено: lit-uriy от Май 17, 2009, 02:49
>>QString это единственный класс отвечающий за строки?
нет есть ещё QByteArray


Название: Re: Инициализация строк.
Отправлено: fynjy от Май 17, 2009, 11:37
а поподробней можно узнать, что ты хочешь сделать? эти макросы я так понял для преобразования char* в QString и они ничего не замеряют
Вторым параметром для функций fromUtf8, fromWCharArray и прочих из той же оперы идёт длина подставляемой строки, которая по умолчанию -1. Так вот я подозреваю, что каждый раз QT меряет длину принимаемой строки в рантайме (может в сырцы слазить убедится что-ли?!) при конструировании класа QString, если установлен параметр по умолчанию. Макросы позволяют замерить длину строки на этапе компиляции. Вопрос: а не изобретаю ли я велосипед?


Название: Re: Инициализация строк.
Отправлено: Авварон от Май 17, 2009, 12:14
по-моему ты не совсем правильно понимаешь работу с++:) даже если компилятор вычислит sizeof(char*) - размер твоей строки (по идее не обязан, но это один из основных способов оптимизации) и подставит это число в вызов ф-ий QString::fromUtf8 и QString::fromWCharArray, то объект он инициализировать не будет - вызов этих ф-ий по-любому будет отложен до рантайма. Разницы в использовании/неиспользовании макросов лишь 1 - с ними не нужно писать ручками sizeof()


Название: Re: Инициализация строк.
Отправлено: fynjy от Май 17, 2009, 14:28
lit-uriy
Спасибо.

Авварон
Речь идёт не о создании объекта в рантайме (я знаю, что компилер будет вызывать коснтруктор), а о вычислении длины строки в рантайме. Подозрения подтвердились: если длина строки не указано явно библиотека считает её в конструкторе (точнее в одной из нескольких вспомогательных функций, что и ожидалось от правильной билиотеки). Объясняю почему нужны макросы: строки в с/с++ заканчиваются нулём и никакой информации о длине строки компилятор не закладывает. Если подобные макросы не используются, то каждый раз библиотека будет перебирать строку в поисках нуля. При использовании макросов это исключается. Да и ещё макросы разворачиваются так:
Код:
QString::fromUtf8("bla bla bla", sizeof("bla bla bla") - 1);
QString::fromWCharArray(L"bla bla bla", sizeof(L"bla bla bla") / 4 -1);
Я уверен что вторым параметром для каждой функции компилер именно подставит цифру (где-то слышал что все константы обязаны быть вычислены во время компиляции проги).

А посему повторяю свой вопрос: имеются ли подобные макросы (или что-то ещё подобное) в QT

PS. я предпочитаю писать эффективные проги. Эффективная работа со строками залог эффективных программ. Кто этого не понимает, я не виноват.


Название: Re: Инициализация строк.
Отправлено: Rcus от Май 17, 2009, 15:03
Таких макросов нет (кстати sizeof(wchar_t) не всегда == 4), только обычно дополнительный вызов qstrlen при аллокации не так значим, как оптимизация на других уровнях.


Название: Re: Инициализация строк.
Отправлено: Авварон от Май 17, 2009, 15:19
вычислить длинну строки времени требует меньше, чем аллокация памяти под эту строку. Я таких макросов не видел


Название: Re: Инициализация строк.
Отправлено: fynjy от Май 17, 2009, 16:23
Ок всем спасибо. Макросы я ещё буду тестить.

UPD. пока остановился на таком варианте:
Код:
#define _L16(aString) QString::fromUtf16(reinterpret_cast<const ushort*>(u##aString), sizeof(u##aString) / sizeof(char16_t) - 1)
#define _L8(aString) QByteArray(aString, sizeof(aString) / sizeof(char) - 1)
Требуется gcc 4.3.2 компиляция должна проходить с флагом -std=c++0x . Для _L16 строка попадает почти сразу и без изменений во внутренние структуры QString (накладные расходы один вызов внутренней функции, который проверяет корректность входных параметров). В общем понятно почему такие макросы ранее не применялись. Это связано с размером wchar_t который колеблется от системы к системе.

Кстати после просмотра сырцов qt оказалось, что например функция QTextStream& QTextStream::operator <<(const char *string) сначала создаёт QString через создание QLatin1String (идёт перекодировка из latin1 в utf16 и определяется длина строки), а уже потом пишет в файл (где тоже, возможно, идёт перекодировка). Кроме того там есть перекодировки в utf16 из utf8, utf32 и пр.

Отдельное спасибо Rcus за упоминание про размер wchar_t.

PS. буду считать это не таким страшным, пока не буду прогать тожде самое под симбу (или какую нить ещё тормозную систему).


Название: Re: Инициализация строк.
Отправлено: Авварон от Май 18, 2009, 16:34
В общем понятно почему такие макросы ранее не применялись. Это связано с размером wchar_t который колеблется от системы к системе.
Потому что они никому не нужны


Название: Re: Инициализация строк.
Отправлено: Alex Custov от Май 18, 2009, 19:59
даже если компилятор вычислит sizeof(char*) - размер твоей строки

sizeof в таком макросе вернёт либо размер указателя, либо действительно размер строки (если передать char []) :)