Какова цель использования фигурных скобок (т. е. {}) для однострочного if или loop?

Я читаю некоторые лекционные заметки моего лектора на C++, и он написал следующее:

  1. использовать отступ / / OK
  2. никогда не полагайтесь на приоритет оператора-всегда используйте круглые скобки / / OK
  3. всегда используйте блок { } - даже для одной строки //не ОК, почему ???
  4. Const объект на левой стороне сравнения / / OK
  5. используйте unsigned для переменных, которые >= 0 / / nice trick
  6. установить Указатель на NULL после удаления-Double delete protection / / неплохо

3-я техника мне не ясна: что бы я получил, поместив одну строку в а { ... }?

например, возьмите этот странный код:

int j = 0;
for (int i = 0 ; i < 100 ; ++i)
{
    if (i % 2 == 0)
    {
        j++;
    }
}

и замените его на:

int j = 0;
for (int i = 0 ; i < 100 ; ++i)
    if (i % 2 == 0)
        j++;

в чем преимущество использования 1-й версии?

23 ответов


давайте попробуем также изменить i когда мы увеличиваем j:

int j = 0;
for (int i = 0 ; i < 100 ; ++i)
    if (i % 2 == 0)
        j++;
        i++;

О нет! Исходя из Python, это выглядит нормально, но на самом деле это не так, поскольку это эквивалентно:

int j = 0;
for (int i = 0 ; i < 100 ; ++i)
    if (i % 2 == 0)
        j++;
i++;

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

еще одна очень важная причина указывается в та.спеот.это ответ.

третий одно я могу думать вложен ifs:

if (cond1)
   if (cond2) 
      doSomething();

теперь, предположим, что вы хотите doSomethingElse(), когда cond1 не выполняется (новая функция). Итак:

if (cond1)
   if (cond2) 
      doSomething();
else
   doSomethingElse();

что, очевидно, неправильно, так как else ассоциируется с внутренней if.


Edit: поскольку это привлекает некоторое внимание, я уточню свое мнение. Вопрос, на который я отвечал:--13-->

в чем преимущество использования 1-й версии?

который я описал. Есть некоторые преимущества. Но, ИМО, правила "всегда" не всегда применимы. Поэтому я не полностью поддерживаю

всегда используйте блок { } - даже для одной строки / / не ОК, почему ???

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


очень легко случайно изменить control-flow с комментариями, Если вы не используете { и }. Например:

if (condition)
  do_something();
else
  do_something_else();

must_always_do_this();

если закомментировать do_something_else() С одной строкой комментария, вы в конечном итоге с этим:

if (condition)
  do_something();
else
  //do_something_else();

must_always_do_this();

он компилирует, но must_always_do_this() не всегда называют.

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


  1. OK
  2. кто-нибудь действительно напишет (или захочет прочитать) (b*b) - ((4*a)*c)? Некоторые прецеденты очевидны (или должны быть), а дополнительные скобки просто добавьте путаницы. (С другой стороны, вы _should_ использовать скобки в менее очевидных случаях, даже если вы знаете, что они не необходимый.)
  3. рода. Существует два широко распространенных соглашения для форматирование условия и циклы:
    if ( cond ) {
        code;
    }
    
    и:
    if ( cond )
    {
        code;
    }
    
    В первом я бы с ним согласился. Открытие { разве это не видно, так что лучше предположить, что он всегда там. Во втором, однако, я (и большинство людей, с которыми я работал) не имеют проблем с опущением скобки для одного оператора. (При условии, конечно, что отступы систематичны и вы используете этот стиль последовательно. (И много очень хороших программистов, пишущих очень читаемый код, опускают брекеты даже при форматировании первым способом.)
  4. нет. Такие вещи, как if ( NULL == ptr ) достаточно уродливы, чтобы помешать удобочитаемость. Пишите сравнения интуитивно. (Что во многих случаях приводит к константе справа.) Его 4-плохой совет; ничего что делает код неестественным, делает его менее читаемым.
  5. нет. Ничего, кроме int зарезервирован для особых случаев. К опытные программисты на C и c++, использование unsigned сигналы бит операторы. C++ не имеет реального кардинального типа (или любого другого эффективный тип поддиапазона); unsigned не работает для числовых значений, из-за правил продвижения. Числовые значения, на которых нет арифметические операции имели бы смысл, как серийные номера, могли бы предположительно unsigned. Однако я бы возражал, потому что это отправляет неправильное сообщение: побитовые операции также не имеют смысла. Основное правило состоит в том, что интегральные типы int, _unless_ существует существенная причина для использования другого тип.
  6. нет. Делать это систематически вводит в заблуждение, и на самом деле не защищать от чего угодно. В строгом коде OO,delete this; часто наиболее частый случай (и вы не можете установить this to NULL), и в противном случае, большинство delete находятся в деструкторах, поэтому вы не можете получить доступ к во всяком случае, позже. И установить его на NULL ничего не происходит о любых других указателях, плавающих вокруг. Установка указателя систематически к NULL дает false чувство безопасности, и не действительно куплю тебе что-нибудь.

посмотрите на код в любой из типичных ссылок. Страуструп нарушает все правила, кроме первого, например.

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


все остальные ответы защищают Правило 3 Вашего лектора.

позвольте мне сказать, что я согласен с вами: правило избыточно и я бы не советовал. Это правда, что это теоретически предотвращает ошибки, если вы всегда добавить фигурные скобки. С другой стороны,--7-->Я никогда не сталкивался с этой проблемой в реальной жизни: вопреки тому, что подразумевают другие ответы, я ни разу не забыл добавить фигурные скобки, как только они стали необходимыми. Если вы используете правильную отступ, сразу становится очевидным, что вам нужно добавить фигурные скобки еще раз, чем один оператор отступа.

ответ "компонент 10" фактически подчеркивает единственный мыслимый случай, когда это действительно может привести к ошибке. Но, с другой стороны, замена кода регулярным выражением всегда требует огромной осторожности.

теперь давайте посмотрим на другую сторону медали: есть минус всегда использовать фигурные скобки? Этот другие ответы просто игнорируют этот момент. Но нет!--9-- > is недостаток: он занимает много вертикального пространства экрана, и это, в свою очередь, может сделать ваш код нечитаемым, потому что это означает, что вам нужно прокручивать больше, чем необходимо.

рассмотрим функцию с большим количеством защитных предложений в начале (и да, следующий плохой код C++, но на других языках это было бы довольно распространенной ситуацией):

void some_method(obj* a, obj* b)
{
    if (a == nullptr)
    {
        throw null_ptr_error("a");
    }
    if (b == nullptr)
    {
        throw null_ptr_error("b");
    }
    if (a == b)
    {
        throw logic_error("Cannot do method on identical objects");
    }
    if (not a->precondition_met())
    {
        throw logic_error("Precondition for a not met");
    }

    a->do_something_with(b);
}

Это ужасный код, и я решительно утверждаю, что следующее значительно более читабельно:

void some_method(obj* a, obj* b)
{
    if (a == nullptr)
        throw null_ptr_error("a");
    if (b == nullptr)
        throw null_ptr_error("b");
    if (a == b)
        throw logic_error("Cannot do method on identical objects");
    if (not a->precondition_met())
        throw logic_error("Precondition for a not met");

    a->do_something_with(b);
}

аналогично, короткие вложенные петли выигрывают от опущения фигурных скобок:

matrix operator +(matrix const& a, matrix const& b) {
    matrix c(a.w(), a.h());

    for (auto i = 0; i < a.w(); ++i)
        for (auto j = 0; j < a.h(); ++j)
            c(i, j) = a(i, j) + b(i, j);

    return c;
}

сравнить с:

matrix operator +(matrix const& a, matrix const& b) {
    matrix c(a.w(), a.h());

    for (auto i = 0; i < a.w(); ++i)
    {
        for (auto j = 0; j < a.h(); ++j)
        {
            c(i, j) = a(i, j) + b(i, j);
        }
    }

    return c;
}

первый код является кратким; второй код раздут.

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

короче говоря: не пишите ненужный код, который занимает место на экране.


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

самый частый проблемный пример, с которым я столкнулся, это:

if ( really incredibly stupidly massively long statement that exceeds the width of the editor) do_foo;
    this_looks_like_a_then-statement_but_isn't;

поэтому, когда я прихожу и хочу добавить тогда-заявление, я могу легко закончить с этим, если я не буду осторожен:

if ( really incredibly stupidly massively long statement that exceeds the width of the editor) do_foo;
{
    this_looks_like_a_then-statement_but_isn't;
    i_want_this_to_be_a_then-statement_but_it's_not;
}

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


мой 2c:

Использовать Отступы

очевидно

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

Я бы не использовал слова "никогда и" всегда", но в целом я вижу, что это правило полезно. В некоторых языках (Lisp, Smalltalk) это не проблема.

всегда используйте блок { } - даже для одной строки

Я никогда этого не делаю и никогда не имел ни одного проблема, но я вижу, как это может быть хорошо для студентов, esp. если они изучали Python ниже.

Const объект на левой стороне сравнения

условия Йоды? Нет, пожалуйста. Это вредит читаемости. Просто используйте максимальный уровень предупреждения при компиляции кода.

используйте unsigned для переменных, которые >= 0

OK. Забавно, но я слышал, что Страуструп не согласен.

установить указатель на NULL после удаление-защита от двойного удаления

плохой совет! Никогда не иметь указатель, который указывает на удаленный или несуществующий объект.


это более интуитивно и легко понятно. Это делает намерение ясным.

и это гарантирует, что код не сломается, когда новый пользователь может неосознанно пропустить {, } при добавлении нового оператора кода.


чтобы добавить к очень разумным предложениям выше, один пример, с которым я столкнулся при рефакторинге некоторого кода, где это становится критическим, был следующим: я изменял очень большую кодовую базу для переключения с одного API на другой. Первый API имел вызов, чтобы установить идентификатор компании следующим образом:

setCompIds( const std::string& compId, const std::string& compSubId );

в то время как замена требовала двух вызовов:

setCompId( const std::string& compId );
setCompSubId( const std::string& compSubId );

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

if ( condition )
   setCompIds( compId, compSubId );

для этого:

if ( condition )
   setCompId( compId );
setCompSubId( compSubId );

что явно не то, что требовалось. Я должен был вернуться к началу сделать это снова, рассматривая замену как полностью внутри блока, а затем вручную изменяя все, что в конечном итоге выглядело глупо (по крайней мере, это не было бы неправильный.)

я заметил, что astyle теперь есть опция --add-brackets что позволяет добавлять скобки, где их нет, и я настоятельно рекомендую это, если вы когда-нибудь окажетесь в том же положении, что и я.


Я использую {} везде, кроме нескольких случаев, когда это очевидно. Одиночная строка является одним из случаев:

if(condition) return; // OK

if(condition) // 
   return;    // and this is not a one-liner 

это может повредить вам, когда вы добавляете какой-то метод перед возвратом. Отступ указывает, что return выполняется при выполнении условия, но он будет возвращаться всегда.

другой пример в C# с использованием statment

using (D d = new D())  // OK
using (C c = new C(d))
{
    c.UseLimitedResource();
}

что эквивалентно

using (D d = new D())
{
    using (C c = new C(d))
    {
        c.UseLimitedResource();
    }
}

самый подходящий пример, который я могу придумать:

if(someCondition)
   if(someOtherCondition)
      DoSomething();
else
   DoSomethingElse();

, который if будет else быть в паре с? Отступ подразумевает, что внешний if получает else, но на самом деле компилятор будет видеть это не так;внутренний if будет else, а внешний if не делает. Вы должны знать это (или видеть, что он ведет себя таким образом в режиме отладки), чтобы выяснить, почему этот код может не оправдать ваших ожиданий. Он становится более запутанным, если вы знаете Python; в этом случае вы знаете, что отступ определяет блоки кода, поэтому вы ожидаете, что он будет оцениваться в соответствии с отступом. C#, однако, не дает летающего сальто о пробелах.

теперь, что сказал, Я не особенно согласен с этим правилом" всегда использовать скобки " на его лице. Это делает код очень вертикально шумным,уменьшая возможность быстро читать его. Если утверждение:

if(someCondition)
   DoSomething();

... затем следует написано вот так. Утверждение "всегда использовать скобки" звучит как "всегда окружать математические операции круглыми скобками". Это превратило бы очень простое утверждение a * b + c / d на ((a * b) + (c / d)), вводя возможность пропустить close-paren (проклятие многих кодеров), и для чего? Порядок операций хорошо известен и хорошо соблюдается, поэтому скобки являются избыточными. Вы бы использовали только круглые скобки для обеспечения другого порядка операций, чем обычно применяется:a * (b+c) / d например. Блочные фигурные скобки похожи; используйте их, чтобы определить, что вы хотите делать в случаях, когда это отличается от значения по умолчанию и не является "очевидным" (субъективным, но обычно довольно здравым смыслом).


просматривая ответы, никто явно не заявил о том, какую практику я привык, рассказывая историю вашего кода:

int j = 0;
for (int i = 0 ; i < 100 ; ++i)
{
    if (i % 2 == 0)
    {
        j++;
    }
}

будет:

int j = 0;
for (int i = 0 ; i < 100 ; ++i)
{
    if (i % 2 == 0) j++;
}

поставить j++ на та же строка как будто должен сигнализировать кому-то еще, " я только хочу, чтобы этот блок постоянно увеличивался j". Конечно, это имеет смысл только в том случае, если линия максимально упрощена, потому что установка точки останова здесь, как Пери упоминает, не будет очень полезно.

на самом деле я только что столкнулся с частью API Twitter Storm, у которого есть этот " вид " кода на java, вот фрагмент фрагмента relvant из кода execute, on страница 43 этого слайд-шоу:

...
Integer Count = counts.get(word);
if (Count=null) count=0;
count++
...

в блоке for loop есть две вещи, поэтому я бы не вставлял этот код. И. Е никогда:

int j = 0;
for (int i = 0 ; i < 100 ; ++i) if (i % 2 == 0) j++;

это ужасно, и я даже не знаю, работает ли это (как намеревался);не делай этого. Новые строки и фигурные скобки помогают различать отдельные, но связанные фрагменты кода, так же как запятая или двоеточие в прозе. Вышеприведенный блок - это действительно длинное предложение с несколькими предложениями и некоторыми другими утверждениями, которые никогда не прерываются или не останавливаются, чтобы различать отдельные части.

если вы действительно хотите телеграфировать кому-то другому, это однострочная работа, используйте троичный оператор или ?: форма:

for (int i = 0 ; i < 100 ; ++i) (i%2 ? 0 : >0) j++;

но это граничит с code-golf, и я думаю, что не большая практика (мне не ясно, должен ли я поставить j++ на одну сторону : или нет). NB я раньше не запускал троичный оператор на C++, я не знаю, работает ли это,но он существует.

короче:

представьте, как ваш читатель (т. е. человек, обслуживающий код) интерпретирует вашу историю (код). Объясните им как можно яснее. Если вы знаете, что начинающий кодер / студент поддерживает это, возможно, даже оставит столько {} насколько это возможно, чтобы они не путались.


потому что когда у вас есть два заявления без {}, легко пропустить проблему. Предположим, что код выглядит так.

int error = 0;
enum hash_type hash = SHA256;
struct hash_value *hash_result = hash_allocate();

if ((err = prepare_hash(hash, &hash_result))) != 0)
    goto fail;
if ((err = hash_update(&hash_result, &client_random)) != 0)
    goto fail;
if ((err = hash_update(&hash_result, &server_random)) != 0)
    goto fail;
if ((err = hash_update(&hash_result, &exchange_params)) != 0)
    goto fail;
    goto fail;
if ((err = hash_finish(hash)) != 0)
    goto fail;

error = do_important_stuff_with(hash);

fail:
hash_free(hash);
return error;

выглядит нормально. Проблема с ним действительно легко пропустить, особенно если функция содержит код намного больше. Проблема в том, что goto fail выполняется безоговорочно. Вы можете легко представить, как это расстраивает (заставляя вас спросить, почему last hash_update всегда терпит неудачу, ведь все выглядит нормально в hash_update функция.)

однако это не означает, что я для добавления {} везде (на мой взгляд, видя {} везде-это раздражает). Хотя это может вызвать проблемы, это никогда не делалось для моих собственных проектов, так как мой личный стиль кодирования запрещает условные обозначения без {} когда они не находятся в одной строке (да, я согласен, что мой стиль кодирования нетрадиционен, но мне это нравится, и я использую стиль кода проекта при внесении вклада в другие проекты). Это делает следующий код штраф.

if (something) goto fail;

но не следующий.

if (something)
    goto fail;

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


wrt 6: это безопаснее, потому что удаление нулевого указателя является no-op. Поэтому, если вы случайно пройдете этот путь дважды, вы не вызовете повреждение памяти, освобождая память, которая либо свободна, либо была выделена для чего-то другого.

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

в большинстве случаев вы можете избежать необходимости с помощью auto_ptrs


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

int j = 0;
for (int i = 0 ; i < 100 ; ++i)
{
    if (i % 2 == 0)
    {
        j++;
    }
}

выглядит загроможденным для меня. Он разделяет цикл for и оператор if на отдельные действия, когда на самом деле ваше намерение-одно действие: подсчитать все целые числа, делимые на 2. На более выразительном языке это могло бы пишется что-то вроде:

j = [1..100].filter(_%2 == 0).Count

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

int j = 0;
for (int i = 0 ; i < 100 ; ++i)
  if (i % 2 == 0)
{
    j++;
}

один из вариантов предотвращения ошибок, описанных выше, - встроить то, что вы хотите сделать, когда вы не используете фигурные скобки. Это значительно затрудняет не заметить ошибки при попытке изменить код.

if (condition) doSomething();
else doSomethingElse();

if (condition) doSomething();
    doSomething2(); // Looks pretty obviously wrong
else // doSomethingElse(); also looks pretty obviously wrong

Если вы не компилятор, это не имеет никакого значения. Оба такие же.

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


еще один пример добавления фигурных скобок. Однажды я искал ошибку и нашел такой код:

void SomeSimpleEventHandler()
{
    SomeStatementAtTheBeginningNumber1;
    if (conditionX) SomeRegularStatement;
    SomeStatementAtTheBeginningNumber2;
    SomeStatementAtTheBeginningNumber3;
    if (!SomeConditionIsMet()) return;
    OtherwiseSomeAdditionalStatement1;
    OtherwiseSomeAdditionalStatement2;
    OtherwiseSomeAdditionalStatement3;
}

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

{
    ...
    OtherwiseSomeAdditionalStatement3;
    SetAnotherVariableUnconditionnaly;
}

В результате SetAnotherVariableUnconditionnaly выполняется, когда SomeConditionIsMet (), но быстрый парень не заметил этого, потому что все линии почти одинаковы по размеру, и даже когда условие возврата вертикально отступлено, это не так заметно.

если условное возвращение отформатировано следующим образом:

if (!SomeConditionIsMet())
{
    return;
}

Это очень заметно, и быстрый кодер найдет его с первого взгляда.


Я считаю, что первый, чтобы быть ясным, то второй. Это дает ощущение закрытия инструкций, с небольшим кодом хорошо, когда код становится сложным {...} помогает, даже если это endif или begin...end

//first
int j = 0;
for (int i = 0 ; i < 100 ; ++i)
{
    if (i % 2 == 0)
    {
        j++;
    }
}


//second
int j = 0;
for (int i = 0 ; i < 100 ; ++i)
    if (i % 2 == 0)
        j++;
i++;

лучше всего установить указатель на NULL, когда вы закончите с ним.

вот пример почему:

класс A делает следующее:

  1. выделяет блок памяти
  2. затем через некоторое время он удаляет этот блок памяти, но не устанавливает указатель на NULL

класс B делает следующее

  1. выделяет память (и в этом случае это происходит с тем же блоком памяти, который был исключено классом A.)

в этот момент как класс A, так и класс B имеют указатели, указывающие на один и тот же блок памяти, что касается класса A, Этот блок памяти не существует, потому что он закончил с ним.

рассмотрим следующую задачу:

Что, если в классе A была логическая ошибка, которая привела к записи в память, которая теперь принадлежит классу B?

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

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

Если бы вы установили указатель удаленной памяти на NULL, вы получили бы ошибку исключения, как только любые логические ошибки в классе A попытались бы написать пустой указатель.

Если вас беспокоит логическая ошибка с двойным удалением, когда указатели во второй раз равны нулю, добавьте assert для этого.

также: если вы собираетесь голосовать, пожалуйста, объясните.


всегда иметь фигурные скобки-это очень простое и надежное правило. Однако код может выглядеть неэлегантно, когда много брекетов. Если правила позволяют опустить фигурные скобки, то должны быть более подробные правила стиля и более сложные инструменты. В противном случае это может легко привести к хаотической и запутанной (не шикарно) код. Поэтому поиск единого правила стиля отдельно от остальных руководств по стилю и используемых инструментов, вероятно, бесплоден. Я просто приведу некоторые важные детали об этом правиле №3 это даже не упоминалось в других ответах.

первая интересная деталь заключается в том, что большинство сторонников этого правила согласны нарушить его в случае else. Другими словами они не требуют в такой код:

// pedantic rule #3
if ( command == Eat )
{
    eat();
}
else
{
    if ( command == Sleep )
    {
        sleep();
    }
    else
    {
        if ( command == Drink )
        {
            drink();
        }
        else
        {
            complain_about_unknown_command();
        }
    }
}

вместо этого, если они увидят это, они могут даже предложить написать это так:

// not fully conforming to rule #3
if ( command == Eat )
{
    eat();
}
else if ( command == Sleep )
{
    sleep();
}
else if ( command == Drink )
{
    drink();
}
else
{
   complain_about_unknown_command();
}

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

третья деталь (которую часто забывают противники этого правила) - это запутанная природа пустого утверждения, которое представлено одной точкой с запятой. Большинство разработчиков, имеющих некоторый опыт, рано или поздно путают единственную неуместную точку с запятой или пустой оператор, написанный с помощью единственной точки с запятой. Две фигурные скобки вместо одной точки с запятой визуально легче обнаружить.


я должен признать, что не всегда использовать {} для одной строки, но это хорошая практика.

  • допустим, вы пишете код без скобок, выглядит так:

    for (int i = 0; i

и через некоторое время нужно добавить в j loop некоторые другие вещи, и вы просто делаете это путем выравнивания и забываете добавить скобки.

  • dealocation памяти быстрее. Допустим, у вас большой объем и вы создаете большие массивы внутри (без new так они находятся в стеке). Эти массивы удаляются из памяти сразу после того, как вы покидаете scope. Но возможно, что вы используете этот массив в одном месте, и он будет некоторое время в стеке и будет каким-то мусором. Поскольку стек имеет ограниченный и довольно небольшой размер, можно превысить размер стека. Так что в некоторых случаях лучше писать {} to предотвратить это. Примечание это не для одной строки, а для таких ситуаций:

    if (...) { //SomeStuff... {//у нас нет if, while и т. д. // SomeOtherStuff } // SomeMoreStuff }

  • Третий способ его использования аналогичен второму. Это просто не сделать стек чище, но открыть некоторые функции. Если вы используете mutex в длинных функциях обычно лучше заблокировать и разблокировать непосредственно перед доступом к данным и сразу после окончания чтения / записи. Примечание этот способ используется если у вас есть свой собственный class или struct С constructor и destructor для блокировки памяти.

  • что еще:

    if (...) если.( ..) SomeStuff(); еще SomeOtherStuff (); //переходит ко второму if, но alligment показывает, что он находится на первом...

в целом, я не могу сказать, какой лучший способ всегда использовать {} для a одна строка, но это не плохо, чтобы сделать это.

ВАЖНОЕ РЕДАКТИРОВАНИЕ если вы пишете компиляцию скобок кода для одной строки, ничего не делает, но если ваш код будет интерпретирован, он очень немного замедляет код. Очень незначительно.


if (condition)
  statement;

будет сосуществовать комфортно с некоторыми другими способами написания управляющих операторов, но не так хорошо с другими. Если многострочные управляемые операторы записываются как:

if (condition)
{
  statement;
  statement;
}

тогда будет визуально очевидно, что if операторы управления a одну линию и контроль нескольких линий. Если, однако, многострочный if заявления пишутся так:

if (condition) {
  statement;
  statement;
}

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

одно-заявление-на-следующей строке if оператор также может быть проблематичным, если кодовая база значительно использует форму

if (condition) statement;

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

if (x1 > xmax) x1 = xmax;
if (x1 < xmin) x1 = xmin;
if (x2 > xmax) x2 = xmax;
if (x2 < xmin) x2 = xmin;
etc.

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