source

한 줄 if 또는 루프에 중괄호(예: {})를 사용하는 목적은 무엇입니까?

manycodes 2022. 11. 15. 21:35
반응형

한 줄 if 또는 루프에 중괄호(예: {})를 사용하는 목적은 무엇입니까?

저는 C++ 강사의 강의 노트를 읽고 있는데, 그는 다음과 같이 썼습니다.

  1. 들여쓰기 사용 // OK
  2. 연산자 우선 순위에 의존하지 않음 - 항상 괄호 사용 // OK
  3. 한 줄이라도 항상 { } 블록을 사용합니다. // 정상이 아닙니다. 이유는 무엇입니까?
  4. 비교 왼쪽에 개체 구성 // OK
  5. >= 0 // nice trick인 변수에 부호 없이 사용
  6. 삭제 후 포인터를 NULL로 설정 - 이중 삭제 보호 // 나쁘지 않음

세 번째 기술은 명확하지 않습니다: 1개의 라인에 배치하면 무엇을 얻을 수 있습니까?{ ... }무슨 일입니까?

예를 들어 다음과 같은 이상한 코드를 예로 들 수 있습니다.

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++;

첫 번째 버전을 사용하면 어떤 이점이 있습니까?

여러분도 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++;

물론, 이것은 어리석은 실수이지만, 숙련된 프로그래머도 할 수 있는 실수이다.

ta.speot.is의 답변에는 또 다른 매우 좋은 이유가 지적되어 있습니다.

가 생각할 수 있는 세 번째 은 네스트이다.if 개요

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

이제 여러분이 '아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아.doSomethingElse()cond1이치노 ★★★★★★★★★★★★★★★★:

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

것이다.else 「」와 .if.


편집: 주목받는 내용이기 때문에 제 견해를 명확히 하겠습니다.제가 대답한 질문은 다음과 같습니다.

첫 번째 버전을 사용하면 어떤 이점이 있습니까?

내가 설명한 대로야몇 가지 장점이 있습니다.하지만 IMO, "항상" 규칙이 항상 적용되는 것은 아닙니다.그래서 나는 전적으로 지지하지 않는다.

한 줄이라도 항상 { } 블록을 사용합니다. // 정상이 아닙니다. 이유는 무엇입니까?

항상 사용하라는 은 아닙니다.{}차단. 간단한 조건과 동작이라면 하지 마세요.나중에 다른 사람이 와서 코드를 변경하여 기능을 추가할 수 있을 것 같으면 그렇게 하십시오.

로 변경하기 하지 않을 { ★★★★★★★★★★★★★★★★★」} §:

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();

찬은 it it it itmust_always_do_this()항상 불리는 것은 아닙니다.

코드 베이스에 이 문제가 있었습니다.출시 전에 누군가가 몇 가지 기능을 즉시 비활성화하기 위해 들어갔습니다.다행히 우리는 코드 리뷰에서 그것을 포착했다.

다른 모든 답변은 강사의 규칙 3을 옹호합니다.

나는 너에게 동의한다고 말할게: 규칙은 불필요하고 나는 그것을 충고하지 않을 거야.확실히 항상 곱슬 괄호를 붙이면 이론적으로 오류를 방지할 수 있습니다.한편, 저는 실제로문제를 접한 적이 없습니다.다른 답변이 시사하는 것과 달리, 필요할 때 괄호를 추가하는 것을 잊은 적이 없습니다.올바른 들여쓰기를 사용하면 여러 개의 문을 들여쓰면 즉시 대괄호를 추가해야 합니다.

"컴포넌트 10"의 답변은 실제로 오류로 이어질 수 있는 유일한 경우를 강조합니다.한편 정규 표현으로 코드를 대체하려면 항상 많은 주의가 필요합니다.

이제 메달의 다른 면을 보자: 항상 곱슬 괄호를 사용하는 것에 단점이 있는가?다른 답변은 이 점을 무시합니다.단, 단점이 있습니다.그 때문에, 화면의 세로 영역이 많아져, 필요 이상으로 스크롤 할 필요가 있기 때문에, 코드를 판독할 수 없게 되는 일이 있습니다.

처음에 guard 구가 많은 함수를 생각해 봅시다(그리고 다음 코드는 불량 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;
}

첫 번째 코드는 간결하고 두 번째 코드는 비대합니다.

네, 앞줄에 오프닝 브레이스를 붙이면 어느 정도 완화할 수 있습니다.그래서: 만약 당신이 곱슬곱슬한 괄호를 고집한다면, 적어도 앞줄에 시작 괄호를 넣으세요.

한마디로 화면 공간을 차지하는 불필요한 코드를 작성하지 마십시오.


원래 답을 쓴 이후로 나는 주로 일반적인 코드 스타일을 받아들이고 앞줄에 문장 전체를 넣을 수 없는 한 중괄호를 사용한다.저는 여전히 용장 브레이스를 사용하지 않는 것이 일반적으로 더 읽기 쉽다고 주장하고 있으며, 이로 인해 발생한 버그는 아직이 없습니다.

나는 그 강사의 역량에 대해 의심이 든다.그의 요점을 고려하면:

  1. 네 알겠습니다
  2. 요?(b*b) - ((4*a)*c)일부 우선순위는 명백하고(또는 그래야 한다) 추가 괄호는 혼란을 가중시킬 뿐이다(반면, 필요하지 않다는 것을 알더라도 덜 명백한 경우에는 괄호를 사용해야 한다).
  3. 루프를 에는 두 . 즉, 조건과 루프를 포맷하는 규칙이 있습니다.
    ( cond )의 경우}코드}
    아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 맞다.
    if ( cond ){코드}
    선,,, 나나나동동동동 것것것것것것것 ★★★★★{눈에 잘 띄지 않기 때문에 항상 거기에 있다고 가정하는 것이 가장 좋습니다.그러나 두 번째, 나(그리고 내가 함께 일했던 대부분의 사람들)는 하나의 스테이트먼트에서 괄호를 생략하는 것은 문제가 없습니다.(물론 들여쓰기가 체계적이고 이 스타일을 일관되게 사용합니다.) (그리고 매우 읽기 쉬운 코드를 쓰는 많은 훌륭한 프로그래머들은 첫 번째 방법으로 포맷할 때에도 괄호를 생략합니다.)
  4. 아니요. 뭐 이런 거if ( NULL == ptr )이치노비교를 직관적으로 작성하십시오. (대부분의 경우 오른쪽 상수가 됩니다.)그의 4는 나쁜 조언이다; 코드를 부자연스럽게 만드는 것은 그것을 읽기 어렵게 만든다.
  5. 아니요. 어떤 것이든int이치노이 풍부한 C및 C경우 C++를 합니다.unsignedoperators.signals bit 'signalsC++로 하다unsigned프로모션 규칙 때문에 숫자 값에는 사용할 수 없습니다.번호와 도, 「」가 될 이 있습니다.unsigned하지만 비트 단위 운영도 의미가 없다는 잘못된 메시지를 전달하기 때문에 반대합니다.은 「」입니다.int다른을 사용해야 중요한 한, _ada는 다른 유형을 사용해야 합니다
  6. 아니요. 체계적으로 하는 것은 오해를 불러일으킬 수 있으며 실제로 어떤 것도 보호하지 않습니다.엄밀한 OO코드로delete this;this로로 합니다.NULL 이외의 는, 「대부분」입니다.delete디스트럭터에 있기 때문에 나중에 포인터에 액세스 할 수 없습니다.그리고 그것을 로 설정한다.NULL떠도는 다른 포인터에 대해서는 아무것도 하지 않습니다.으로 「」으로 한다.NULL잘못된 안정감을 주면서 아무것도 사주지 않는 거죠

일반적인 레퍼런스의 코드를 확인합니다.Strustrup은 예를 들어 첫 번째 규칙을 제외하고 당신이 준 모든 규칙을 위반합니다.

다른 강사를 찾으시길 권합니다.자기가 무슨 말을 하는지 잘 아는 사람이죠

보다 직관적이고 쉽게 이해할 수 있습니다.그것은 의도를 분명히 한다.

, 에 「 않게 있습니다.{,}새 코드 문을 추가하는 동안.

제가 작업하고 있는 코드 베이스는 교정기를 싫어하는 사람들이 코드와 함께 산재되어 있습니다.그리고 나중에 오는 사람들은 코드 베이스가 유지보수에 큰 변화를 가져올 수 있습니다.

가장 빈번하게 발생하는 문제의 예는 다음과 같습니다.

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초가 걸리고 디버깅이 혼란스러운 몇 분 동안 단축될 수 있는데 굳이 reduced-markity 옵션을 사용하지 않는 이유는 무엇입니까?나한테는 잘못된 경제인 것 같아.

위의 매우 합리적인 제안을 덧붙이자면, 이것이 중요해지는 몇 가지 코드를 리팩터링하는 동안 접한 한 가지 예는 다음과 같습니다.API 간에 전환하기 위해 매우 큰 코드베이스를 변경하고 있었습니다.첫 번째 API에서는 다음과 같이 Company Id를 설정하기 위한 호출이 있었습니다.

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

교환에는 2개의 콜이 필요했습니다.

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

저는 정규 표현을 사용해서 이것을 바꾸기로 했습니다.그것은 매우 성공적이었습니다.또한 암호를 아스타일에 전달해서 훨씬 더 읽기 쉽게 만들었습니다.그 후, 검토 프로세스 도중에, 몇개의 조건적인 상황에서, 이것이 이것을 변화시키고 있는 것을 알게 되었습니다.

if ( condition )
   setCompIds( compId, compSubId );

이를 위해:

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

그건 분명히 필요했던 것이 아니었어요.처음부터 다시 한 번 이 작업을 수행해야 했습니다. 교체를 블록 내에서 완전히 처리한 후 이상하게 보이는 모든 작업을 수동으로 수정해야 했습니다(적어도 틀리지는 않을 것입니다.

이제 아스타일이 선택권을 가지고 있다는 걸 알게 됐어요--add-brackets괄호가 없는 곳에 괄호를 붙일 수 있습니다.만약 저와 같은 입장에 서게 된다면, 이것을 강력히 추천합니다.

10년 동안 캠프에서 "항상 교정기를 사용한다"고 한 후, 저는 최근에 교정기를 많이 사용하지 않는 것으로 바꿨습니다.깨끗한 코드를 쓰는 방법에 대한 밥 삼촌의 주장에 대부분 영감을 받아 나는 이제 괄호 없이 쓰는 것이 더 읽기 쉽다고 믿는다.

if(guardClause)
      throw new SomeException(..)

밥 아저씨는 if/for 문장에 코드를 두 줄 이상 쓰는 것은 잠재적인 가독성 냄새라고 주장한다.

예.

if(someCondition)
{
   doTechnicalThingX();
   doTechnicalThingY();
   doTechnicalThingZ();
}

다음과 같이 리팩터링해야 합니다.

if(someCondition)
    doFunctionalThingA();

왠지 교정기를 끼우지 않는 것이 도움이 됩니다.왜냐하면 if 블록 안에 너무 많은 코드를 쓰고 있다는 것을 상기시키기 때문입니다.

코드 스타일은 다른 사람들이 말한 것처럼 팀 결정이라고 생각합니다.

마이 2c:

들여쓰기 사용

물론. 뻔하지.

연산자 우선 순위에 의존하지 않음 - 항상 괄호 사용

저는 "절대"와 "항상"이라는 단어를 사용하지 않지만, 일반적으로 이 규칙이 유용하다고 생각합니다.일부 언어(Lisp, Smalltalk)에서는 이 문제가 발생하지 않습니다.

한 줄이라도 항상 { } 블록 사용

저는 그런 적도 없고, 어떤 문제도 없었습니다만, 학생들이 Python을 공부한 적이 있다면, 그것이 어떻게 학생들에게 좋을지 알 수 있습니다.

비교 왼쪽에 개체 구성

요다 상태?아니, 제발.가독성을 해칩니다.코드를 컴파일할 때 최대 경고 수준을 사용하십시오.

>= 0인 변수에 부호 없이 사용

좋아, 재미있군 스트루스트럽이 반대한다고 들었어

삭제 후 포인터를 NULL로 설정 - 이중 삭제 보호

나쁜 충고!삭제되었거나 존재하지 않는 개체를 가리키는 포인터를 갖지 마십시오.

{}이슈를 놓치기 쉽습니다.코드가 이렇게 생겼다고 가정해 봅시다.

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;

츠키노특히 코드를 포함하는 함수가 훨씬 더 클 경우 이 문제를 놓치기 쉽습니다.는 문는 the the the the the thegoto fail무조건 실행됩니다.할 수 .hash_update가 잘 hash_update★★★★★★★★★★★★★★★★★★」

제가 더하는 것은 .{}{}사방이 귀찮다).은 문제가 될 수 , 제 개인 코딩 스타일은 문제가 없는 조건들을 하고 있기 에 제가 되지 .{}같은 선상에 있지 않은 경우(예, 제 코딩 스타일은 틀에 박히지 않지만, 마음에 들고, 다른 프로젝트에 공헌할 때는 프로젝트의 코드 스타일을 사용합니다).이것에 의해, 다음의 코드가 양호하게 됩니다.

if (something) goto fail;

하지만 다음 것은 아니다.

if (something)
    goto fail;

답을 훑어보니 아무도 내가 습관적으로 사용하는 방식을 명확하게 말하지 않았습니다. 당신의 코드에 대한 이야기를 들려준다.

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++if가 다른 사람에게 "I want this block only ever increment"라는 신호를 보내는 행과 같은 행에 있습니다.물론 courseth는 선이 최대한 단순할 경우에만 가치가 있습니다. 왜냐하면 peri가 언급했듯이 여기에 중단점을 두는 것은 그다지 유용하지 않기 때문입니다.

사실 방금 Java 코드 '일종의'을 가진 Twitter Storm API의 일부를 발견했습니다.이 슬라이드 쇼의 43페이지에 있는 실행 코드의 relvant 스니펫을 나타냅니다.

...
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++;

끔찍하고 (의도대로) 되는지도 모르겠어요. 이러지 마세요.새 줄과 중괄호는 산문의 쉼표 또는 세미콜론과 같은 방식으로 분리되지만 관련된 코드 조각을 구별하는 데 도움이 됩니다.위의 블록은 몇 개의 절과 다른 문장으로 구분하기 위해 끊기거나 멈추는 일이 없는 매우 긴 문장입니다.

다른 사람에게 전신을 보내려면 3진수 연산자 또는 양식을 사용하여 한 줄짜리 작업입니다.

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

은 거의 에 가깝기 연습은 :또는 말 것)을 참조해 주세요.NB 저는 C++에서 3진 연산자를 실행한 적이 없습니다.이것이 효과가 있을지는 모르겠지만, 존재합니다.

요컨대:

독자(즉, 코드를 관리하는 사람)가 자신의 이야기(코드)를 어떻게 해석하는지 상상해 보십시오.★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★을 유지하고 있다는 을 알고 있다면, 수의 코더/학생을 수도 있습니다.{}★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★

하고 .{}1행이다이다.

if(condition) return; // OK

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

반품 전에 몇 가지 방법을 추가하시면 다칠 수 있습니다.들여쓰기는 조건이 충족될 때 반환이 실행 중이지만 항상 반환됨을 나타냅니다.

스테이트먼트를 사용한 C#의 다른 예

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아아아아아아아아아아아아아아아아아아아아.이 '아우터'를 하고 있습니다.ifelse하지만 컴파일러는 실제로 그렇게 생각하지 않습니다.내부는 if else및, " " "if그렇지 않다.이 코드가 예상에 어긋나는 원인을 검사하여 알아내야 합니다(또는 디버깅모드에서 이와 같이 동작하고 있는 것을 확인할 필요가 있습니다.Python을 알면 더 혼란스러울 수 있습니다.이 경우 들여쓰기가 코드 블록을 정의한다는 것을 알 수 있기 때문에 들여쓰기에 따라 평가될 것으로 예상됩니다.그러나 C#은 공백에 대해서는 전혀 신경 쓰지 않습니다.

즉, 저는 이 "항상 괄호를 사용한다"는 규칙에 그다지 동의하지 않습니다.코드 세로 노이즈가 매우 심해져 코드를 빠르게 읽을 수 없게 됩니다.스테이트먼트가 다음과 같은 경우:

if(someCondition)
   DoSomething();

이렇게 ...이렇게 써있어야 합니다."항상 괄호를 사용한다"는 문장은 "항상 수학 연산을 괄호로 둘러싸라"는 것처럼 들린다. 문장이 .a * b + c / d((a * b) + (c / d))코더의 골칫덩어리(많은 코더의 골칫덩어리)를 놓칠 가능성을 소개하며, 그 이유는 무엇입니까?동작 순서는 잘 알려져 있고 적용도 잘 되어 있기 때문에 괄호는 중복되어 있습니다.보통되는 조작 와는 다른 합니다.a * (b+c) / d '으로는 상당히 상식적인 사용합니다.블록 중괄호는 비슷합니다.기본값과 다르며 "명백한"(주관적이지만 일반적으로는 상당히 상식적인) 경우에 수행할 작업을 정의하기 위해 사용합니다.

루프와 조건부 블록의 범위를 명확하게 정의함으로써 코드를 보다 읽기 쉽게 만듭니다.그것은 또한 우발적인 실수로부터 여러분을 구합니다.

wrt 6: 늘 포인터를 삭제할 수 없기 때문에 더 안전합니다.따라서 실수로 이 경로를 두 번 통과하더라도 메모리 손상이 발생하지 않고 사용 가능한 메모리나 다른 곳에 할당되어 있는 메모리를 해방할 수 있습니다.

이는 정적 파일 범위 개체와 싱글톤이 수명이 명확하지 않고 파괴된 후 다시 생성되는 것이 대부분입니다.

대부분의 경우 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개의 다른 단순 이벤트 핸들러처럼 보입니다.어느 날 Fast Coder가 와서 메서드 끝에 변수 설정문을 추가합니다.

{
    ...
    OtherwiseSomeAdditionalStatement3;
    SetAnotherVariableUnconditionnaly;
}

그 결과 SomeConditionIsMet()에서는 SetAnotherVariableUnconditionnaly가 실행되지만 모든 행의 크기가 거의 비슷하고 반환 조건이 수직으로 삽입되어도 그다지 눈에 띄지 않기 때문에 빠른 사람은 알아차리지 못했습니다.

조건부 반환 형식이 다음과 같은 경우:

if (!SomeConditionIsMet())
{
    return;
}

매우 눈에 띄기 때문에 Fast Coder가 한눈에 알 수 있습니다.

나는 첫 번째 것이 명확하고 두 번째 것이 확실하다고 생각한다.듯한 .{...} 이 되다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가 예기치 않은 값을 발견하면 최종적으로 크래쉬 할 수 있습니다.크래쉬 했을 경우 문제가 클래스A에 있을 때 클래스B에서 이 버그를 찾는데 오랜 시간이 걸릴 가능성이 있습니다.

삭제된 메모리 포인터를 NULL로 설정한 경우 클래스 A의 논리 오류가 NULL 포인터에 쓰려고 하면 즉시 예외 오류가 발생합니다.

포인터가 두 번째 NULL일 때 이중 삭제 로직 오류가 우려되는 경우 이를 위해 아사트를 추가합니다.

또, 부결투표를 할 예정이라면, 설명해 주세요.

항상 물결 괄호를 사용하는 것은 매우 간단하고 견고한 규칙입니다.단, 교정기가 많을 경우 코드가 우아해 보일 수 있습니다.규칙에서 물결 괄호를 생략할 수 있다면 보다 상세한 스타일 규칙과 보다 정교한 도구가 있어야 합니다.그렇지 않으면 혼란스럽고 혼란스러운(고상하지 않은) 코드가 생기기 쉽습니다.따라서 사용되는 스타일 가이드 및 도구와 별도로 단일 스타일 규칙을 찾는 것은 효과가 없을 수 있습니다.다른 답변에서는 언급되지도 않은 규칙 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이러한 규칙의 이중성은 의식 없는 도구를 사용하여 자동으로 코드 베이스에 적용하려고 할 때 표면화됩니다.과연, 왜 논쟁할 필요가 있겠는가, 단지 스타일을 자동으로 적용하는 도구를 놔두면 된다.

두 번째 세부사항(그 규칙의 지지자들에 의해 종종 잊혀진다)은 발생할 수 있는 오류는 규칙 #3의 위반 때문만은 아니라는 것입니다.사실 그것들은 거의 항상 규칙 1번 위반을 수반한다(아무도 이의를 제기하지 않는다.다시 말하면, 자동 툴의 관점에서 보면, 룰 #1을 위반했을 때에 즉시 불만을 제기하는 툴을 만드는 것은 어렵지 않기 때문에, 대부분의 에러는 적시에 검출할 수 있습니다.

세 번째 세부사항(이 규칙의 반대자가 자주 잊어버린다)은 단일 세미콜론으로 나타나는 빈 스테이트먼트의 혼동을 일으키는 성질입니다.경험이 있는 대부분의 개발자는 세미콜론만 잘못 배치하거나 세미콜론만 사용하여 빈 문장으로 인해 조만간 혼란을 겪게 됩니다.단일 세미콜론 대신 두 개의 물결 괄호를 사용하면 시각적으로 훨씬 쉽게 찾을 수식별할 수 있습니다.

사용하시는 것은 을 인정합니다.{}츠키노

  • 다음과 같은 대괄호 없이 코드를 작성했다고 가정합니다.

    (int i = 0; i < 100; ++i)의 경우 (int j = 0; j < 100; ++j) DoSingleStuff();

조금 '아예'를 예요.j다른 것을 루프하면 정렬만 하고 괄호를 추가하는 것을 잊게 됩니다.

  • 메모리 할당이 더 빠릅니다., 이 큰 있고 내부에 수 가정해 봅시다.new스택에 있습니다).이러한 어레이는 범위를 벗어나자마자 메모리에서 삭제됩니다.하지만 그 어레이를 한 곳에서 사용하면 한동안 쌓여서 쓰레기가 될 수 있습니다.스택의 사이즈는 한정되어 있고 매우 작기 때문에 스택사이즈를 초과할 수 있습니다. 경우에 이렇게 쓰는 수 .{}그걸 막으려고요주의: 이것은 단일 회선이 아니라 그러한 상황에 대한 것입니다.

    (...) {//Something Stuff...{//우리는 if, while 등 //SomeOtherStuff} //SomeMoreStuff}가 없습니다.

  • 세 번째 사용법은 두 번째와 비슷합니다.스택을 깔끔하게 하기 위해서가 아니라 몇 가지 기능을 열기 위해서입니다.사용하시는 경우mutex긴 기능에서는 일반적으로 데이터에 액세스하기 직전에, 그리고 읽기/쓰기를 마친 직후에 잠금을 해제하는 것이 좋습니다.주의: 이 방법은 고객님이 가지고 계신 경우에 사용합니다.class ★★★★★★★★★★★★★★★★★」structconstructor ★★★★★★★★★★★★★★★★★」destructor메모리를 잠급니다.

  • 기타 정보:

    (...) SomeStuff()인 경우, SomeOtherStuff()인 경우, //가 두 번째 if로 이동하지만 악어는 첫 번째가 켜져 있음을 나타냅니다.

으로 말하면, 수 .{}단 한 줄이면 되는데 그렇게 해도 나쁠 건 없어요.

중요 편집 코드 괄호를 한 줄에 컴파일할 경우 아무 작업도 하지 않지만 코드가 해석될 경우 코드가 매우 약간 느려집니다.아주 조금.

제어문을 작성하는 방법에는 여러 가지가 있습니다.특정 조합은 가독성을 해치지 않고 공존할 수 있지만 다른 조합은 문제를 일으킬 수 있습니다.스타일

if (condition)
  statement;

컨트롤 스테이트먼트를 작성하는 다른 방법과는 편안하게 공존할 수 있지만 다른 방법과는 잘 어울리지 않습니다.여러 줄의 제어 스테이트먼트가 다음과 같이 기술되어 있는 경우:

if (condition)
{
  statement;
  statement;
}

어느 쪽이 더 이다.if문은 단일 행과 여러 행을 제어하는 행을 제어합니다.,경우if스테이트먼트는 다음과 같이 작성됩니다.

if (condition) {
  statement;
  statement;
}

의 문구를 하려고 할 이 있습니다.if필요한 중괄호를 추가하지 않은 구성은 훨씬 더 높을 수 있습니다.

줄의 단일 if, 베이스가 「Code Base」의 을 많이 하고 있는 에도, 가 될 이 있습니다.

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같은 움푹 들어간 부분이 뭔가 이상하다는 명확한 시각적 징후를 제공합니다.

언급URL : https://stackoverflow.com/questions/12193170/whats-the-purpose-of-using-braces-i-e-for-a-single-line-if-or-loop

반응형