Макросы, чтобы избежать выделения кучи? В этом случае это плохо? - PullRequest
2 голосов
/ 02 сентября 2010

Это мой первый вопрос, и это нубистский вопрос:).

Я сталкиваюсь с проблемой с C ++ и Qt 4.6, потому что я хочу разложить часть своего кода, которая вызывает какой-то общедоступныйслоты QObject с помощью метода QMetaMethod :: invoke ().

Проблема, с которой я сталкиваюсь, заключается в том, что макрос Q_ARG определяется следующим образом:

#define Q_ARG(type, data) QArgument<type >(#type, data)

То естьчто я должен знать во время компиляции тип.Но с другой стороны, я получаю свои аргументы для метода, которые приходят как QVariants.Я могу получить их типы через метод доступа -> type (), который возвращает значение перечисления типа QVariant :: Type, но, естественно, не как тип времени компиляции.

Таким образом, чтобы просто генерировать аргументы для вызова,Я сделал следующий макрос:

#define PASS_SUPPORTED_TYPE(parameterToFill, requiredType, param, supported) {      \
                                            \
        switch (requiredType) {                         \
            case QVariant::String:                      \
                parameterToFill = Q_ARG(QString,            \
                        param.value<QString>());        \
            break;                              \
                                            \
            case QVariant::Int:                         \
                parameterToFill = Q_ARG(int, param.value<int>());   \
            break;                              \
                                                        \
            case QVariant::Double:                      \
                parameterToFill = Q_ARG(double, param.value<double>()); \
            break;                              \
                                                        \
            case QVariant::Char:                        \
                parameterToFill = Q_ARG(char, param.value<char>());     \
            break;                              \
                                                        \
            case QVariant::Bool:                        \
                parameterToFill = Q_ARG(bool, param.value<bool>());     \
            break;                              \
                                                        \
            case QVariant::Url:                         \
                parameterToFill = Q_ARG(QUrl, param.value<QUrl>());     \
            break;                              \
                                                        \
            default:                            \
                supported = false;                  \
                                            \
        }                                   \
                                            \
        supported = true;                           \
}

То же самое можно было бы сделать в методе, который мог бы возвратить true или false вместо установки флага «поддерживаемого», но это заставило бы меня сделать выделение кучи в этом случаепотому что вызов "param.value ()" возвращает копию значения QVariant, которое я должен хранить в куче через новый или через memset.

И это моя проблема, я не хочуделать выделение кучи в этом методе, потому что он будет вызываться тысячи раз (это модуль обработки запросов).

for (int k = 0; k < methodParams.size(); ++k) {
    QVariant::Type paramType = QVariant::nameToType(methodParams[k].toAscii());

    [...]

    bool supportedType = false;

    PASS_SUPPORTED_TYPE(
            paramsToPass[k], 
            paramType, 
            params[k],
            supportedType);
   [...]
}

metaMethod.invoke(objectToCall, paramsToPass[0], paramsToPass[1], paramsToPass[2] [...]);

Это меня не радует, потому что это небезопасно.Поэтому я задаю себе вопрос: как я могу запустить этот макрос и заменить его на метод, который будет выполнять выделение стека, а не выделение кучи?

Заранее благодарю всех за помощь и интерес.

1 Ответ

4 голосов
/ 02 сентября 2010

И это моя проблема, я не хочу сделать выделение кучи в этом методе, потому что это будет называться тысячами времени (это обработка запроса модуль).

Не переоценивайте проблемы с выступлениями. Да, выделение стека происходит быстрее, и да, нужно избегать копий, когда они не нужны. Однако для меня это выглядит как преждевременная оптимизация .

Кажется, вы строите очень сложную архитектуру кода, чтобы сэкономить несколько циклов ЦП. В конце концов, вы не сможете достоверно сказать, что вызывается и сколько раз. И у вас будет не поддерживаемый код.

Мой совет: сосредоточьтесь на правильности и простоте вашего кода и, если в какой-то момент вы действительно столкнетесь с проблемами производительности, профиль вашего кода, чтобы увидеть, что не так.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...