Вы используете фигурные скобки для дополнительного определения объема? [закрытый]
Я имею в виду, кроме использования его, когда это требуется для функций, классов, if, while, switch, try-catch.
Я не знал, что это можно сделать, как это, пока я не увидел этот так Вопрос.
В приведенной выше ссылке Эли упомянул, что "они используют его, чтобы свернуть свой код в логические разделы, которые не попадают в функцию, класс, цикл и т. д. это обычно было сложено."
Какие еще существуют применения, кроме упомянутых?
Хорошо ли использовать фигурные фигурные скобки, чтобы ограничить область ваших переменных и расширить область только в случае необходимости (работая на основе" need-to-access")? Или это действительно глупо?
Как насчет использования областей просто так, чтобы вы могли использовать одни и те же имена переменных в разных областях, но в одной и той же большей области? Или лучше использовать одну и ту же переменную повторно (если вы хотите использовать одно и то же имя переменной) и сэкономить на освобождении и выделении (я думаю, некоторые компиляторы могут оптимизировать на этом?)? Или лучше использовать разные имена переменных вообще?
13 ответов:
Я делаю, если я использую ресурс, который я хочу освободить в определенное время, например:
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
Это может быть благом для генераторов кода. Предположим, у вас есть встроенный компилятор SQL (ESQL); он может захотеть преобразовать инструкцию SQL в блок кода, которому нужны локальные переменные. Используя блок, он может повторно использовать имена фиксированных переменных снова и снова, вместо того, чтобы создавать все переменные с отдельными именами. Конечно, это не слишком трудно, но все же труднее, чем необходимо.
Как уже говорили другие, это довольно распространено в C++ из-за всемогущей идиомы RAII (Resource acquisition is initialization)/pattern.
Для Java-программистов (и, возможно, C#, я не знаю) это будет чужеродная концепция, потому что объекты на основе кучи и GC убивают RAII. ИМХО, возможность помещать объекты в стек является самым большим преимуществом C++ по сравнению с Java и делает хорошо написанный код C++ намного чище, чем хорошо написанный код Java.
Я использую его только тогда, когда мне нужно освободить что-то с помощью RAII, и даже тогда, когда это должно быть освобождено как можно раньше (например, освобождение блокировки).
Программирование на Java я довольно часто хотел ограничить область применения метода, но мне никогда не приходило в голову использовать метку. Поскольку я заглавными буквами пишу свои метки, когда использую их в качестве цели разрыва, использование смешанного блока с меткой case, как вы предложили, - это именно то, что я хотел в этих случаях.
Часто блоки кода слишком коротки, чтобы разбиться на небольшой метод, и часто код в методе фреймворка (например, startup () или 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); } }
Я согласен с agartzke. Если вы чувствуете, что вам нужно сегментировать большие логические блоки кода для удобства чтения, вы должны рассмотреть возможность рефакторинга, чтобы очистить занятые и загроможденные элементы.
У него есть свое место, но я не думаю, что делать это так, чтобы $foo могла быть одной переменной здесь и другой переменной там, в пределах той же функции или другой (логической, а не лексической) области-хорошая идея. Даже при том, что компилятор может понять это в совершенстве, кажется слишком вероятным, что это затруднит жизнь для людей, пытающихся прочитать код.
Компания, в которой я работаю, имеет политику статического анализа, чтобы держать объявления локальных переменных рядом с началом функции. Во многих случаях используется много строк после первой строки функции, поэтому я не могу видеть объявление и первую ссылку одновременно на экране. То, что я делаю, чтобы "обойти" политику, состоит в том, чтобы держать объявление рядом со ссылкой, но предоставлять дополнительную область с помощью фигурных скобок. Это увеличивает отступ, хотя, и некоторые могут утверждать, что это делает код уродливее.