Используете ли вы фигурные скобки для дополнительной области видимости?[закрыто]
-
05-07-2019 - |
Вопрос
Я имею в виду, кроме использования его, когда это необходимо для функций, классов, if, while, switch, try-catch.
Я не знал, что это можно сделать так это пока я не увидел этот ТАК вопрос.
В приведенной выше ссылке Эли упомянул, что «Они используют его, чтобы сложить свой код в логические разделы, которые не попадают в функцию, класс, цикл и т. д.обычно его складывают».
Какие еще существуют варианты использования, кроме упомянутых?
Хорошая ли идея использовать фигурные скобки, чтобы ограничить область действия ваших переменных и расширять ее только при необходимости (работая по принципу «необходимости доступа»)?Или это действительно глупо?
Как насчет использования областей, чтобы вы могли использовать одни и те же имена переменных в разных областях, но в одной и той же большей области?Или лучше повторно использовать одну и ту же переменную (если вы хотите использовать одно и то же имя переменной) и сэкономить на освобождении и выделении памяти (я думаю, некоторые компиляторы могут это оптимизировать?)?Или лучше вообще использовать разные имена переменных?
Решение
Я делаю, если использую ресурс, который я хочу освободить в определенное время, например:
void myfunction()
{
{
// Open serial port
SerialPort port("COM1", 9600);
port.doTransfer(data);
} // Serial port gets closed here.
for(int i = 0; i < data.size(); i++)
doProcessData(data[i]);
etc...
}
Другие советы
Я бы не стал использовать фигурные скобки для этой цели по нескольким причинам.
<Ол>Если ваша конкретная функция достаточно велика, чтобы вам приходилось выполнять различные фокусы, возможно, разбейте ее на более мелкие подфункции.
Введение фигурных скобок для повторного использования имен переменных только приведет к путанице и проблемам в коде.
Просто мои 2 цента, но я видел много таких вещей в других лучших практических материалах.
Наиболее распространенный "нестандартный" Я регулярно использую область видимости, чтобы использовать мьютекс с областью действия.
void MyClass::Somefun()
{
//do some stuff
{
// example imlementation that has a mutex passed into a lock object:
scopedMutex lockObject(m_mutex);
// protected code here
} // mutex is unlocked here
// more code here
}
Это имеет много преимуществ, но самое главное, что блокировка всегда будет очищаться, даже если в защищенном коде выдается исключение.
С++:
Иногда вам нужно ввести дополнительный уровень скобок для повторного использования имен переменных, когда это имеет смысл:
switch (x) {
case 0:
int i = 0;
foo(i);
break;
case 1:
int i = 1;
bar(i);
break;
}
Код выше не компилируется.Вам нужно сделать это:
switch (x) {
case 0:
{
int i = 0;
foo(i);
}
break;
case 1:
{
int i = 1;
bar(i);
}
break;
}
Наиболее распространенное использование, как уже говорили другие, это обеспечение работы деструкторов, когда вы этого хотите. Это также удобно для того, чтобы сделать специфичный для платформы код немного более понятным:
#if defined( UNIX )
if( some unix-specific condition )
#endif
{
// This code should always run on Windows but
// only if the above condition holds on unix
}
Код, созданный для Windows, не видит if, только фигурные скобки. Это намного понятнее, чем:
#if defined( UNIX )
if( some unix-specific condition ) {
#endif
// This code should always run on Windows but
// only if the above condition holds on unix
#if defined( UNIX )
}
#endif
Это может быть благом для генераторов кода. Предположим, у вас есть компилятор Embedded SQL (ESQL); он может захотеть преобразовать инструкцию SQL в блок кода, который нуждается в локальных переменных. Используя блок, он может многократно использовать фиксированные имена переменных, вместо того, чтобы создавать все переменные с разными именами. Конечно, это не так сложно, но это сложнее, чем необходимо.
Как уже говорили другие, это довольно часто встречается в C ++ благодаря идиоме / шаблону всепоглощающего RAII (получение ресурсов - инициализация).
Для программистов на Java (и, возможно, на C #, я не знаю) это будет чужой концепцией, потому что объекты на основе кучи и GC убивают RAII. ИМХО, возможность помещать объекты в стек - это величайшее единственное преимущество C ++ над Java, и делает хорошо написанный код C ++ НАМНОГО чище, чем хорошо написанный код Java.
Я использую его только тогда, когда мне нужно освободить что-либо с помощью RAII, и даже тогда, только когда это должно быть выпущено как можно раньше (например, снятие блокировки).
Программирование на Java Мне часто хотелось ограничить область действия метода, но мне никогда не приходило в голову использовать метку.Поскольку я записываю свои метки в верхний регистр, когда использую их в качестве цели разрыва, использование блока с метками в смешанном регистре, как вы предложили, - это именно то, что мне нужно в таких случаях.
Часто блоки кода слишком коротки, чтобы их можно было разбить на небольшой метод, а часто и код в методе платформы (например, start() или Shutdown()), и на самом деле лучше хранить код вместе в одном методе.
Лично я ненавижу простые плавающие/висячие скобки (хотя это потому, что мы являемся магазином со строгими отступами в стиле баннеров), и я ненавижу маркер комментария:
// yuk!
some code
{
scoped code
}
more code
// also yuk!
some code
/* do xyz */ {
scoped code
}
some more code
// this I like
some code
DoXyz: {
scoped code
}
some more code
Мы рассматривали возможность использования «if(true) {», потому что в спецификации Java прямо указано, что они будут оптимизированы при компиляции (как и все содержимое if(false) — это функция отладки), но в некоторых местах мне это не нравилось. Я попробовал это.
Так что я думаю, что ваша идея хорошая, совсем не глупая.Я всегда думал, что я единственный, кто хочет это сделать.
Да, я использую эту технику из-за RAII. Я также использую эту технику в простом C , поскольку она сближает переменные. Конечно, я должен подумать о том, чтобы разбить функции еще больше.
Одна вещь, которую я делаю, что, вероятно, стилистически противоречива, это поставить открывающую фигурную скобку на строку декларации или поставить правильный комментарий к ней. Я хочу уменьшить количество потерянного вертикального пространства. Это основано на рекомендации Руководства по стилю Google C ++. .
/// c++ code
/// references to boost::test
BOOST_TEST_CASE( curly_brace )
{
// init
MyClass instance_to_test( "initial", TestCase::STUFF ); {
instance_to_test.permutate(42u);
instance_to_test.rotate_left_face();
instance_to_test.top_gun();
}
{ // test check
const uint8_t kEXP_FAP_BOOST = 240u;
BOOST_CHECK_EQUAL( instance_to_test.get_fap_boost(), kEXP_FAP_BOOST);
}
}
Я согласен с Агарцке. Если вы чувствуете, что вам нужно сегментировать большие блоки логического кода для удобства чтения, вам следует подумать о рефакторинге, чтобы очистить занятые и загроможденные члены.
Он имеет свое место, но я не думаю, что делать это так, чтобы $ foo могла быть одной переменной здесь и другой переменной там , в пределах одной и той же функции или другая (логическая, а не лексическая) сфера - хорошая идея. Несмотря на то, что компилятор может это прекрасно понимать, кажется, что он слишком труден для людей, пытающихся прочитать код.
Компания, в которой я работаю, имеет политику статического анализа, позволяющую хранить объявления локальных переменных в начале функции. Часто после первой строки функции используется много строк, поэтому я не вижу объявления и первой ссылки одновременно на экране. То, что я делаю, чтобы «обойти» политику, - это сохранить объявление рядом со ссылкой, но предоставить дополнительную область с помощью фигурных скобок. Хотя это увеличивает отступы, и некоторые могут утверждать, что это делает код более уродливым.