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

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

Страниц: [1]   Вниз
  Печать  
Автор Тема: инициализация безразмерного массива в ст  (Прочитано 9021 раз)
Karl-Philipp
Гость
« : Январь 27, 2010, 18:59 »

Всем привет!
Есть такая структура
Код
C++ (Qt)
struct TableDescriptor {
   QString tableName;
   QString header[];
   int hiddenColumn[];
};

Хочется инициализировать структуру как-то так:
Код
C++ (Qt)
TableDescriptor tableMachines = {"machines", {"Id","Machine Name","Power","Speed", QString::null}, {0}};
в ответ компилятор ругается:
error: too many initializers for 'QString [0 ] '
error: too many initializers for 'int [0 ]'
Подскажите, пожалуйста, как правильно сделать?
Записан
niXman
Гость
« Ответ #1 : Январь 27, 2010, 19:06 »

упс..
Записан
Rcus
Гость
« Ответ #2 : Январь 27, 2010, 19:21 »

Размер струтуры должен быть известен во время компиляции, поэтому использовать безразмерные массивы как часть структуры не получится. Нужно вам хранить POD в струтурированном виде так и делайте так. Посмотрите как в ядре сделано: либо терминирование 0, либо запись размера массива рядом с указателем на содержимое.
Записан
BRE
Гость
« Ответ #3 : Январь 27, 2010, 19:37 »

Как вариант:
Код
C++ (Qt)
typedef QList<int> IntList;
struct TableDescriptor    
{                          
       TableDescriptor( const QString &tn, const QStringList &hdr, const IntList &hc ) :
               tableName( tn ), header( hdr ), hiddenColumn( hc )                      
       {                                                                                
       }                                                                                
 
       QString         tableName;
       QStringList     header;  
       IntList         hiddenColumn;
};                                  
 
...
 
TableDescriptor tableMachines( "machines", QStringList() << "Id" << "Machine Name" << "Power" << "Speed", IntList() << 1 << 2 );
 
Записан
Karl-Philipp
Гость
« Ответ #4 : Январь 27, 2010, 20:17 »

спасибо всем Улыбающийся

Размер струтуры должен быть известен во время компиляции, поэтому использовать безразмерные массивы как часть структуры не получится. Нужно вам хранить POD в струтурированном виде так и делайте так. Посмотрите как в ядре сделано: либо терминирование 0, либо запись размера массива рядом с указателем на содержимое.
последнее встречал в литературе. Интересно, а где именно это в ядре, подскажите, куда копать? Захотелось посмотреть Улыбающийся
« Последнее редактирование: Январь 27, 2010, 20:35 от terlan » Записан
Tonal
Гость
« Ответ #5 : Январь 28, 2010, 08:37 »

Часто можно встретить такой трюк:
Код:
struct TableDescriptor {
    QString tableName;
    char header[1];
};
TableDescriptor* f(const QString &tableName, const char header[]) {
  TableDescriptor* ret = static_cast<TableDescriptor*>(
    ::operator new char(sizeof(TableDescriptor) + strlen(header)));
  ret->tableName = tableName
  strcpy(ret->header, header);
  return ret;
}
Некоторые компиляторы допускают не указывать размер в последнем члене массиве, если предполагается использовать эту технику (нестандартно).
Да, такой массив может быть только последний и только один (догадайся почему). Улыбающийся
Кроме того, типы с нетривиальными деструкторами там хранить не рекомендуется (догадайся почему). Улыбающийся
Массив из таких объектов создавать крайне не рекомендуется (догадайся почему). Улыбающийся
Записан
Karl-Philipp
Гость
« Ответ #6 : Январь 28, 2010, 12:07 »

Tonal, не осилил Улыбающийся
давайте пройдемся по методу f:
1) передаем в него ссылку на QString и массив символов неопределенной длины;
2) создаём символ char и инициализируем его числом, состоящим из суммы размера структуры и размера передаваемого массива (я почему-то подумал, что тут квадратные скобки нужны для создания массива символов заданной длины В замешательстве)
3) самое сложное: преобразовываем символ со значением (числом) в структуру;
(у Страуструпа говорится "static_cast осуществляет преобразование родственных типов, например указателя на один тип к указателю на другой тип из той же иерархии классов, целый тип в перечисление... ". А здесь получается преобразование символа в структуру)
Правильно ли я понял?

Ответы на вопросы:
1. Не нашёл ответ!
2. Возможно потому, что данные деструкторы не будут вызываться в нужное время.
3. Возможно потому, что массив элементов константный. Улыбающийся
Записан
BRE
Гость
« Ответ #7 : Январь 28, 2010, 16:09 »

Думаю, имелось ввиду следующее:
Код:
    ::operator new char[ sizeof(TableDescriptor) + strlen(header) ]

Но меня сильно смущает в этой структуре (TableDescriptor) объект класса QString (tableName). Конструктор по умолчанию для него не вызывается, думаю он нормально не сконструируется.
« Последнее редактирование: Январь 28, 2010, 16:49 от BRE » Записан
Tonal
Гость
« Ответ #8 : Январь 29, 2010, 09:31 »

Да, накосячил, таки давно серьёзно с плюсами не возился.
Правильная версия функции:
Код
C++ (Qt)
TableDescriptor* f(const QString &tableName, const char header[]) {
 TableDescriptor* ret = new (
   ::operator new (sizeof(TableDescriptor) + strlen(header))
   //new char[sizeof(TableDescriptor) + strlen(header)] //можно и так :)
 ) TableDescriptor;
 ret->tableName = tableName
 strcpy(ret->header, header);
 return ret;
}
 
Собственно такие трюки очень распространены в чистом С с его POD структурами. Вот я и забыл про конструктор. Улыбающийся

2 terlan всё происходит так:
1. Принимаем параметры.
2. Выделяется память в размере sizeof(TableDescriptor) + strlen(header).
3. В ней конструируется объект TableDescriptor (размещаюший new - placement new).
4. В орбъекте заполняются значения полей. (почему влезет header понятно?)

Удаляется такой объект стандартным delete вполне корректно. Улыбающийся
Но в С++ есть более удобные способы хранить массивы - например как std::vector. Поэтому подобная техника применяется либо для совместимости с чистым С или железом, либо для каких-то суровых оптимизаций работы с памятью.
Хотя в последнем случае правильный менеджер кучи скорее всего даст больший эффект без этих заморочек. Улыбающийся
Записан
Karl-Philipp
Гость
« Ответ #9 : Январь 29, 2010, 15:25 »

Цитата: Tonal
...4. В орбъекте заполняются значения полей. (почему влезет header понятно?)...
понятно, вроде бы. Мы же выделили выделили место под структуру (с учетом размера передаваемого в функцию массива). Однако член структуры char header[1] можно инициализировать большим количеством элементов, чем заявлено.
Вот тут-то возник вопрос, если строка символов (в структуре) содержит 1 элемент, как разместятся другие элементы? Строка же у нас строго ограничена '\0' Улыбающийся
Экспериментирую!
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


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