2014-11-11 2 views
11

Вот то, что мы пытаемся сделатьпопытка {....} задвижка (..) только если определенное выражение во время компиляции верно

try { 
    std::uninitialized_copy(...); 
} catch(...) { 
    if(!boost::has_trivial_destructor<T>::value) { 
     // some cleanup to do here... 
    } 
    throw; 
} 

Мы задаемся вопросом, имеет ли попробовать/поймать стоимость, если константа времени компиляции в if является ложной.

Может ли компилятор в пределах своих прав «как-бы» удалить попытку улова и вести себя как-будто вызов std::uninitialized_copy появился без try вокруг него?

Или есть что-то скрытое в спецификациях C++, которое требует, чтобы компилятор оставил его здесь? В качестве примера предположим гипотетическую функцию surrounding_try_blocks(), которая возвращает динамические окружающие числа проб, отсчитываемых в настоящее время вокруг кадра.

+0

Не могли бы вы разработать свой question.Like, когда вы говорите, «действительно попытаться/поймать имеет стоимость «Какую цену вы имели в виду. Простое размещение блоков try/catch имеет некоторую производительность. – ravi

+0

Если я понимаю вопрос, это: if 'boost :: ...'истинно, тогда код можно было бы оптимизировать только до вызова' unitialized_copy', так как все, что он делает, улавливает исключение, а затем снова бросает его. Но компилятор разрешил эту оптимизацию? – Tommy

+0

, если компилятор оптимизирует оператор if, ваша программа функционирует точно так же, как и без блоков try/catch, нет? Таким образом, я не вижу, что надстройка для компилятора должна быть оптимизирована. –

ответ

0

Ниже я подвел итоги использования исключения, которое я сопоставил из разных источников. Как то, что вы просите в своем втором пункте, мне не очень понятно. Поэтому я подумал, что лучше всего через тебя все. Надеюсь, вы поймете что-то важное.

Чтобы обрабатывать исключения во время выполнения, программы должны выполнять значительную сумму бухгалтерского учета. В каждой точке во время выполнения они должны иметь возможность идентифицировать объекты, требующие уничтожения, если выбрано исключение; они должны обратить внимание на каждую запись и выйти из блока try; и для каждого блока try они должны отслеживать связанные клаузулы catch и типы исключений, которые могут обрабатывать эти статьи.

Есть вещи, за которые вы платите, даже если вы никогда не используете какие-либо функции обработки исключений. Вы платите за пространство , используемое структурами данных, необходимыми для отслеживания того, какие объекты полностью сконструированы, и вы платите за время, необходимое для поддержания этих данных в актуальном состоянии. Эти затраты обычно довольно скромны.

Тем не менее, программа, скомпилированная без поддержки исключений, как правило, быстрее и меньше, чем их коллеги скомпилирован с поддержкой исключений

+4

Но это не отвечает на вопрос. «Может ли компилятор в пределах своих прав« как-если »удалить улов try и вести себя как-если бы вызов' std :: uninitialized_copy' появился без 'try' вокруг него?». Другими словами, может ли быть устранена вся работа, которую вы описываете, поскольку компилятор может (в принципе) видеть, что это не нужно? –

0

С 15,1/8 мы находим

Вбрасывания-выражение, без операндов rethrows в настоящее время обработано исключение (15.3). Исключение возобновляется с существующим временным; нет нового объекта временного исключения не создается ...

Для меня это достаточно очевидно, следует, что при условии оценки boost::has_trivial_destructor<T>::value тривиально можно показать, не имеют побочных эффектов, которые компилятор должен иметь возможность легко определить, что весь основной массы уловка не выполняется и что вся конструкция может быть оптимизирована. Я не знаю конкретного компилятора, который делает/не делает этого, однако.

Мое единственное (небольшое) сомнение заключается в том, считает ли язык очистку и сброс std::uncaught_exception() в соответствии с предложением «как-если».

1

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

template <class T> 
typename boost::enable_if_t<boost::has_trivial_destructor<T>::value, void> 
wrap_uninitialized_copy (...) { 
    std::uninitialized_copy(...); 
} 

template <class T> 
typename boost::enable_if_t<!boost::has_trivial_destructor<T>::value, void> 
wrap_uninitialized_copy (...) { 
    try { 
     std::uninitialized_copy(...); 
    } catch(...) { 
     // some cleanup to do here... 
     throw; 
    } 
} 
Смежные вопросы