Russian Qt Forum

Qt => Общие вопросы => Тема начата: Yuriy от Август 26, 2011, 00:52



Название: C++ переменные
Отправлено: Yuriy от Август 26, 2011, 00:52
Извиняюсь конечно за столь глупый вопрос, но на протяжении последних 2-х лет я так и не уловил, как лучше объявить константный тип, например:
Код:
const QString &aDeleteGroupID = "DELETE FROM TGroups WHERE GrID = '%1';";
или так:
Код:
const QString aDeleteGroupID = "DELETE FROM TGroups WHERE GrID = '%1';";
Понимаю что при вызове функции указатели жизненно необходимы, а как с константами внутри класса ?
Приношу еще раз свои извинения за туфтологию, но хотелось бы узнать.


Название: Re: C++ переменные
Отправлено: kambala от Август 26, 2011, 03:59
определённо второй вариант, только значение присваивать лучше в cpp-файле


Название: Re: C++ переменные
Отправлено: Yuriy от Август 26, 2011, 04:20
интересно... а если я запишу вот так:
Код:
const QString aDeleteGroupID("DELETE FROM TGroups WHERE GrID = '%1';");
это не будет тем же самым, что и первый вариант с использованием &

Я так понимаю, что если в аргументах функции я указываю параметр const type&, тогда функция получает ссылку на участок памяти, не создавая заново эти переменные, не создавая стек параметров по эти переменные и т.д.
А во втором случае по-моему, сначала создается переменная QString, инициализируется, затем рассчитывается вторая половина записи, потом первой присваивается вторая и это на пару тактов больше чем & или нет ????


Название: Re: C++ переменные
Отправлено: Пантер от Август 26, 2011, 07:30
Если Type имеет конструктор Type (SomeType), то
Type t (someType) и Type t = someType идентичны.

А первый вариант неверен.


Название: Re: C++ переменные
Отправлено: Igors от Август 26, 2011, 09:52
Я так понимаю, что если в аргументах функции я указываю параметр const type&, тогда функция получает ссылку на участок памяти, не создавая заново эти переменные, не создавая стек параметров по эти переменные и т.д.
Нет. Сначала создается безымянная QString (вызывается конструктор QString( const char *)), а потом ее адрес присваивается ссылке aDeleteGroupID. Это не ошибка но будет работать для глобальных переменных, а напр вот так получите по ушам
Код
C++ (Qt)
const QString & GetName( void )
{
const QString & name = "abc";
return name;
}
 
Безымянная QString разрушена, возвращена invalid ссылка

А во втором случае по-моему, сначала создается переменная QString, инициализируется, затем рассчитывается вторая половина записи, потом первой присваивается вторая и это на пару тактов больше чем & или нет ????
Если переменная объявлена и присваивается - то вызывается конструктор
Код
C++ (Qt)
QString s1;
s1 = "123";       // здесь оператор присваивания
QString s2 = "123";  // а здесь конструктор QString(const char *)
 
Для POD типов разницы нет

Итого: первый вариант = ненужные выкрутасы


Название: Re: C++ переменные
Отправлено: Пантер от Август 26, 2011, 10:07
Разве QString(const char *) - конструктор копирования? Это обычный конструктор.
QString s2 = s1 - вот копирующий конструктор.


Название: Re: C++ переменные
Отправлено: Igors от Август 26, 2011, 10:22
Разве QString(const char *) - конструктор копирования? Это обычный конструктор.
QString s2 = s1 - вот копирующий конструктор.
Верно, исправил - вызывается "подходящий" конструктор (не обязательно копирования)


Название: Re: C++ переменные
Отправлено: Пантер от Август 26, 2011, 10:38
А мне больше нравится вариант:
const QString aDeleteGroupID = "DELETE FROM TGroups WHERE GrID = '%1';";
Как-то более красиво и удобно. Но это все сугубо дело личных предпочтений. Минус в том, что в случае конструктора explicit с двумя параметрами, где второй дефолтный, так уже не сделать.


Название: Re: C++ переменные
Отправлено: Авварон от Август 26, 2011, 14:35
омг, глобал статик не-поды


Название: Re: C++ переменные
Отправлено: brankovic от Август 26, 2011, 14:47
омг, глобал статик не-поды

омг, глобал статик


Название: Re: C++ переменные
Отправлено: Yuriy от Август 26, 2011, 16:57
Хорошо, тогда такая ситтуация: создаю неимоверно важную функцию с переменным числом параметров:
Код:
bool MyModel::haveValuesAtRow(const int aRow,...) const
{
//aRow - номер строки для поиска
//а далее идут номера столбцов, которые будут игнорироваться при поиске
QVector<int> aIgnoredColumns;

   va_list ap;
   int arg;
   va_start(ap, aRow);
   while ((arg = va_arg(ap,int)) != -1) {
      aIgnoredColumns.append(arg);
   }
   va_end(ap);
   
for (int i = 0; i < columnCount(); ++i)
{
    if (aIgnoredColumns.contains(i)) continue;
    if (!data(index(aRow,i),Qt::EditRole).toString().isEmpty()) return true;
}

return false;
}

Если я запишу в объявлении функции:
Код:
bool MyModel::haveValuesAtRow(const int &aRow,...) const
тогда получается интересная ситтуация!

Под Debian GCC - работает как и прежде, под nmake в список параметров попадает мусор из памяти, вместо переданных 5-10 значений я имею тысячу, в виде int(!) и так до тех пор , пока случайно не наткнусь на int = -1.

Это значит, что под Visual C++ действительно работают константные указатели и переменные не создаются заново, поэтому если первым параметром будет const &type то он и перебросит на участок памяти, где собственно и заложен этот const

А если использовать GCC, то возникают сомнения в работоспособности const указателей в аргументах функций. Судя по этим экспериментам он создает заново эти параметры и заново выделяет под них память.


Название: Re: C++ переменные
Отправлено: Yuriy от Август 26, 2011, 17:05
Млин, не могу найти кнопку "Спасибо"
Поэтому, Пантер и Igors, спасибо за Ваши ответы. Они достаточно обоснованные и мне бы хотелось услышать еще Ваше мнение.


Название: Re: C++ переменные
Отправлено: Yuriy от Август 26, 2011, 17:19
Использую активно библиотеки OpenCascade и там очень часто встречаю случай:
Код:
const type &SomeType = ....
вот как раз в этом самом SomeType в конструкторе заложена масса операций, например, если это линия, то создается тело, ему присваются аттрибуты, цвет и т.д.
Поэтому я думаю что при использовании &SomeType игнорируется базовая инициализация. Создается константная переменная со значением которое следует за знаком =


Название: Re: C++ переменные
Отправлено: Пантер от Август 26, 2011, 18:48
[не по теме]
Не используй функции с переменным числом параметров.
[/не по теме]


Название: Re: C++ переменные
Отправлено: Yuriy от Август 26, 2011, 18:53
ПОЧЕМУ так жестоко ?? Я конечно понимаю что это своеобразный "костыль", но порой удобно !


Название: Re: C++ переменные
Отправлено: Пантер от Август 26, 2011, 18:57
Потому что это не безопасный си-вэй стиль.


Название: Re: C++ переменные
Отправлено: Igors от Август 26, 2011, 21:13
ПОЧЕМУ так жестоко ?? Я конечно понимаю что это своеобразный "костыль", но порой удобно !
Удобно для UI, когда число параметров колеблется 2-5 (остальные по умолчанию) и они разных типов. А с номерами столбцов - не в масть, они все одного типа. да и  потенциально их может быть много. В QSet их - и подавать этот QSet по константной ссылке. Вызывать никак не хуже

Код
C++ (Qt)
haveValuesAtRow(QSet <int> () << 1 << 4 << 6);
 
А будет больше - спокойно зарядить в QSet окремо


Название: Re: C++ переменные
Отправлено: Yuriy от Август 26, 2011, 23:03
Да и вправду. хотя всякие сишные Prinf пользуют arg, лучше без них, дабы избежать выгребания из оперативы мусора.
А что насчет инициализации и операторов присваивания, все же я склонен к тому, что нужно избегать базовой инициализации, если результирующее значение известно до присваивания значения. Речь не только о QString, а также о более увесистых классах, при создании которых вешаются дефолтные свойства класса, а то и вызов конструкторов других классов.


Название: Re: C++ переменные
Отправлено: Igors от Август 27, 2011, 11:24
А что насчет инициализации и операторов присваивания, все же я склонен к тому, что нужно избегать базовой инициализации, если ..
Базовой инициализации не избежать. Если у класса есть конструктор(ы) - невозможно создать экземпляр без того чтобы один из них вызвался (и это правильно).


Название: Re: C++ переменные
Отправлено: Yuriy от Август 28, 2011, 12:28
Это мысль, я думаю что в этом и проблема многих классов, базовая инициализация такая, как будто пользователь не знает, для чего и с чем едят этот класс. А посему было правильней, я сейчас думаю, конструктор оставлять пустым, а в придачу к классу функция, например Init(). Т.е. пользователь создает пустой класс, грубо говоря название, а затем инициалирует его , а если у него есть готовое решение, тогда присваивает с помощь "=". Это правильный ход мыслей ???


Название: Re: C++ переменные
Отправлено: brankovic от Август 28, 2011, 12:45
конструктор оставлять пустым, а в придачу к классу функция, например Init()

В C++ такой вариант возможен, но никто так не делает. Это во-первых неудобно (забудешь init () и получишь падение), а во-вторых ненужно, т.к. базовая инициализация, как правило, тривиальна и не сказывается производительности.