Возможный дубликат:
Могу ли я использовать блоки для управления областью переменных в C ++?
Я наткнулся на некоторый код C ++, который напоминал:
int main(void) {
int foo;
float qux;
/* do some stuff */
{
int bar;
bar = foo * foo;
qux = some_func(bar);
}
/* continue doing some more stuff */
}
Первоначально я думал, что, возможно, первоначальный автор использовал фигурные скобки для группировки некоторых связанных переменных, но, поскольку проектируемая система не имеет достаточного количества памяти, я подумал, что автор мог иметь намерение бара разрешение области видимости и любые переменные с in уходят, вместо того, чтобы иметь их вокруг для всего включения (Foo-х) объем.
Есть ли причина для этого? Мне кажется, в этом нет необходимости, и что любой современный компилятор делает это ненужным?
Мне кажется, в этом нет необходимости, и что любой современный компилятор делает это ненужным?
Да, современные компиляторы оптимизируют использование памяти в подобных случаях. Дополнительная область не сделает код быстрее или более эффективным в использовании памяти.
Тем не менее, они не могут оптимизировать объекты с помощью деструкторов с побочными эффектами, так как это изменило бы поведение программы. Таким образом, это имеет смысл делать для таких объектов.
Есть ли причина для этого?
Полезно группировать связанный код вместе. Вы знаете, что переменные, объявленные внутри фигурных скобок, не будут использоваться где-либо еще, что крайне полезно знать.
В случае C / C ++ можно попытаться ограничить конфликты между именами (иметь такую длинную функцию, для которой требуется переменная области видимости, — плохая идея …), т.е. если есть несколько bar
в той же функции, что и их область видимости, это позволит убедиться, что они не сталкиваются / не перекрывают друг друга.
Обычно область видимости внутри функции не влияет на размер выделения стека — стек предварительно выделяется для всех локальных переменных независимо от области видимости.
Если код действительно такой, как вы показали, возможно, это бессмысленно. Большинство компиляторов, которые я видел, выделяют пространство для всех локальных переменных при входе в функцию и освобождают его при выходе из функции. Есть несколько других возможностей, хотя.
Если то, что вы показали как bar
был объект некоторого типа класса (особенно что-то с деструктором), деструктор работал бы при выходе из области видимости, даже если пространство не было освобождено до позже.
Другая возможность состоит в том, что на самом деле два внутренние области:
int main() {
// ...
{
// some variables
}
// ...
{
// other variables
}
}
В этом случае пространство для локальных переменных будет выделено при входе в main
— но, some variables
а также other variables
будет (обычно) занимать одно и то же место. Т.е. выделенного пространства будет достаточно для размещения большего из двух, но не будет (как правило) суммой двух, как вы бы использовали, если бы вы определили все переменные в main
Сфера.
Если вы делаете это несколько раз в одном методе, это может привести к тому, что этот метод займет меньше места в стеке, в зависимости от вашего компилятора. Если у вас ограниченные ресурсы, возможно, вы используете микроконтроллер, и их компиляторы не всегда так полнофункциональны, как компиляторы x86.
Кроме того, если вы делаете это с полными классами (вместо целых & плавает), это позволяет вам контролировать, где деструктор вызывается.
class MyClass;
int main(void) {
int foo;
float qux;
/* do some stuff */
{
MyClass bar;
qux = some_func(bar);
} // <-- ~MyClass() called here.
/* continue doing some more stuff */
}
намерение иметь разрешение области видимости бара и любые переменные с в ходу
прочь, а не иметь их вокруг для всего вложения (фу)
объем
Это может быть один (неважно, & наследие) причина.
Другая причина заключается в том, чтобы донести до читателя, что int bar
просто используется в этой области, чтобы иметь очень маленькую функциональность (вид функции внутри функции). После этого нет смысла bar
,
Ваш код эквивалентен:
inline void Update (int &foo, float &qux)
{
int bar = foo * foo;
qux = some_func(bar);
}
int main ()
{
...
Update(foo, qux);
...
}
Большинство компиляторов будет оптимизировать вызов Update()
внутри main()
и вставьте его, который генерирует аналогично тому, что вы опубликовали.
Скорее всего, это должно помочь программисту, а не оптимизировать вывод, поскольку современный компилятор, безусловно, достаточно умен, чтобы видеть, что временная переменная используется только один раз.
С другой стороны, для программиста это добавляет логическое разделение, это означает, что «эти переменные нужны только для этого кода» и, возможно, также «этот код не влияет на другой код в этой функции».