2013-08-16 1 views
0

Редактировать: Я знаю, что объявление объекта перед телом цикла более эффективно, так как он вызывает конструктор и деструктор для вызова функции, а не один раз на итерацию цикла. Допустим, что объекты типа A более эффективны вне тела цикла из-за этих рассуждений.более эффективно создавать статические локальные объекты C++

мне интересно, если следующий

void foo() 
{ 
    static A var; //A is a class with a constructor 
    ... //stuff done with var 
} 

является более эффективным, чем

void foo() 
{ 
    A var; //A is a class with a constructor 
    ... //stuff done with var 
} 

, так как первый назвал бы конструктор в и деструктор один раз, а не тот, который делает это за вызов обув , Я задаю этот вопрос в основном по всем локальным объектам.

ответ

1

Прежде всего, это семантически отличается. Вы сравниваете две разные вещи. Если вас не интересует семантическая разница, то она может быть быстрее, чем другая. Если конструкция A не делает многого, например, просто инициализирует int, вполне возможно, что вторая версия выполняется быстрее, например, потому что компилятор должен знать, инициализировал ли он var во время выполнения и на C++ 11 инициализация потокобезопасна. Если конструкция A несколько задействована, скорее всего, первая версия будет быстрее.

Единственный способ узнать какое-либо данное приложение - измерить.

+0

Ну, в общем случае, если конструктор не будет иметь значения для остальных объектов, то первое будет лучше (если конструктор достаточно большой) – bathtub

+0

@bathtub нет, это далеко не важная разница , – Yakk

+0

О, спасибо за это. Действительно оцените это – bathtub

1

Правило большого пальца: укажите, что вы имеете в виду (локальный объект или его логически необходимо использовать для каждого вызова?), И пусть компилятор беспокоится об оптимизации.

Я делаю исключение для констант нетривиальных типов. Например, «static const std :: string» лучше, чем «const std :: string», потому что он сохраняет динамическое распределение каждый раз. Но если объект не содержит динамических распределений и не имеет десятков байтов в размере, сделайте его локальной переменной.

Нет необходимости в создании базовых типов (например, const int или const char *const) статических по соображениям эффективности, хотя это не повредит.

Поскольку статический объект разделяется между потоками, компилятору, возможно, потребуется проверить, что он не обновлялся другим потоком каждый раз, когда ему нужно его использовать, что не может иметь место для локальной переменной. Поэтому не предполагайте, что статический будет «самым быстрым». (Как это работает, зависит от вашей реализации компилятора)

Конечно, вам также необходимо понять, как сделать его статическим или нет, может изменить поведение вашей программы. Моя информация выше предполагает, что выбор не будет.

+0

Так что константы, которые используются при каждом статическом вызове, более эффективны. В основном это произошло со мной при работе с объектами, которые служили временными объектами, которые позже будут перенесены в вектор или что-то в этом направлении. Когда в цикле было более эффективно строить вне тела цикла, а не каждую итерацию. Поэтому я решил, что это применимо к этому situtation – bathtub

+0

@bathtub. Я бы не стал беспокоиться об этом. Если он слишком медленный, вы можете оптимизировать его позже. Лучше сначала создать рабочее решение. Кроме того, компилятор может оптимизировать множество вещей (особенно, если A является простым), поэтому он может не иметь никакого значения. Я имею в виду, что это возможно, но подождите, пока это не будет иметь значения. –

1

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

Вот несколько упрощен пример:

void f(int j) { 
    static int i = 0; 
    i = 0; // reset, because previous call left i with some spurious value 
    while (i < j) 
     std::cout << i << '\n'; 
} 

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