한 줄에 변수를 선언하고 다음 줄에 변수를 할당하는 이유는 무엇입니까? NULL; ptr = &something_else; 대신에 some_type val

나는 종종 C 및 C ++ 코드에서 다음과 같은 규칙을 봅니다.

some_type val;
val = something;

some_type *ptr = NULL;
ptr = &something_else;

대신에

some_type val = something;
some_type *ptr = &something_else;

처음에는 이것이 범위의 맨 위에 모든 지역 변수를 선언해야했던 시절부터 남은 습관이라고 가정했습니다. 그러나 나는 베테랑 개발자의 습관을 너무 빨리 무시하지 않는 법을 배웠습니다. 그렇다면 한 줄로 선언하고 나중에 할당해야 할 합당한 이유가 있습니까?



답변

C89에서 모든 선언 범위 ( { ... }) 의 시작 부분에 있어야 했지만이 요구 사항은 빠르게 떨어졌습니다 (먼저 컴파일러 확장과 표준이 있음).

C ++

이 예제는 동일하지 않습니다. 기본 some_type val = something;생성자를 val = something;호출 한 다음 operator=함수 를 호출하는 동안 복사 생성자를 호출합니다 . 이 차이는 종종 중요합니다.

버릇

어떤 사람들은 변수를 먼저 선언하고 나중에 한 지점에서 선언하고 다른 지점에서 정의를 사용하여 코드를 다시 포맷하는 경우 나중에 변수를 선언하는 것을 선호합니다.

포인터에 관해서는, 어떤 사람들은 포인터로 무엇을 하든지 NULL또는 nullptr에 대한 모든 포인터를 초기화하는 습관을 가지고 있습니다 .


답변

질문 C와 C ++에 동시에 태그를 달았지만이 언어에서는 답이 크게 다릅니다.

먼저, 질문 제목의 문구가 잘못되었습니다 (또는 더 정확하게는 질문 자체와 관련이 없음). 두 예제 모두에서 변수는 한 줄에 동시에 선언되고 정의 됩니다. 예제의 차이점은 첫 번째 변수에서 변수가 초기화되지 않거나 더미 값으로 초기화 다음 나중에 의미있는 값 이 할당 된다는 것입니다 . 두 번째 예에서 변수는 즉시 초기화 됩니다.

둘째, C ++ 언어에서 @nightcracker가 그의 답변에서 언급 했듯이이 두 구성은 의미 상 다릅니다. 첫 번째는 초기화에 의존하고 두 번째는 할당에 의존합니다. C ++에서 이러한 작업은 오버로드 가능하므로 잠재적으로 다른 결과를 초래할 수 있습니다 (비록 동일한 초기화 및 할당의 오버로드를 생성하는 것은 좋지 않습니다).

원래 표준 C 언어 (C89 / 90)에서 블록 중간에 변수를 선언하는 것은 불법이므로 블록의 시작 부분에 초기화되지 않은 (또는 더미 값으로 초기화 된) 변수가 선언 된 후 의미있는 변수가 할당 될 수 있습니다 나중에 의미있는 값을 사용할 수있게됩니다.

C99 언어에서는 블록 중간에 변수를 선언하는 것이 좋습니다 (C ++에서와 같이). 첫 번째 접근 방식은 선언 시점에서 이니셜 라이저를 알 수없는 특정 상황에서만 필요합니다. (이것은 C ++에도 적용됩니다).


답변

“로컬 선언”시대에 남은 오래된 습관이라고 생각합니다. 따라서 귀하의 질문에 대한 답변으로 : 아니요 좋은 이유가 있다고 생각하지 않습니다. 나는 그것을 직접하지 않습니다.


답변

나는에서 그것에 대해 뭔가 말했다 내 대답Helium3하여 질문을 .

기본적으로 변경된 내용을 쉽게 볼 수있는 시각적 도구라고합니다.

if (a == 0) {
    struct whatever *myobject = 0;
    /* did `myobject` (the pointer) get assigned?
    ** or was it `*myobject` (the struct)? */
}

if (a == 0) {
    struct whatever *myobject;
    myobject = 0;
    /* `myobject` (the pointer) got assigned */
}

답변

다른 답변은 꽤 좋습니다. C에는 이것에 관한 몇 가지 역사가 있습니다. C ++에는 생성자와 할당 연산자 사이에 차이가 있습니다.

아무도 추가 요점에 대해 언급하지 않았습니다. 선언을 변수 사용과 분리하여 유지하는 것이 때로는 더 읽기 쉽습니다.

시각적으로 말하자면, 코드를 읽을 때 변수의 유형 및 이름과 같은 더 평범한 인공물은 당신에게 튀어 나와 있지 않습니다. 그것은 당신이 일반적으로 가장 관심이 있고, 쳐다 보는 데 많은 시간을 할애 하는 진술 이므로 나머지를 한눈에 보는 경향이 있습니다.

동일한 유형의 공간에서 일부 유형, 이름 및 할당이 진행되는 경우 약간의 정보 과부하가 발생합니다. 또한, 내가 일반적으로 살펴 보는 공간에서 중요한 것이 진행되고 있음을 의미합니다.

말하기에는 다소 직관적이지 않을 수 있지만 소스가 더 수직 공간을 차지하게하면 더 좋을 수 있습니다. 나는 이것이 좁은 수직 공간에서 엄청난 양의 포인터 산술 및 할당을 수행하는 잼으로 채워진 줄을 작성해서는 안되는 이유와 유사하다고 생각합니다. 언어가 그러한 것들을 피할 수 있다고해서 그렇게해야한다는 의미는 아닙니다. 항상. 🙂


답변

C에서, 이것은 C ++에서와 달리 함수가 시작될 때 변수가 함수 본문의 어느 곳에서나 선언 될 수있을 때와 같이 함수 시작시 선언되어야했기 때문에 표준 관행이었습니다. 포인터가 가비지 없음을 가리 키도록하기 때문에 포인터가 0 또는 NULL로 설정되었습니다. 그렇지 않으면 내가 생각할 수있는 중요한 이점이 없으므로 누군가가 그렇게 할 수 있습니다.


답변

변수 정의 지역화 및 의미있는 초기화에 대한 장점 :

  • 변수가 코드에 처음 나타날 때 습관적으로 의미있는 값이 할당되면 (같은 관점에서 또 다른 관점 : 의미있는 값이 유효 할 때까지 모양을 지연시키는 경우) 실수로 의미가 없거나 초기화되지 않은 값 으로 사용될 가능성은 없습니다 ( 조건문, 단락 평가, 예외 등으로 인해 실수로 일부 초기화가 우회되는 경우 쉽게 발생할 수 있음)

  • 효율적일 수있다

    • 초기 값 설정의 오버 헤드를 피합니다 (기본 구성 또는 NULL과 같은 일부 센티넬 값으로 초기화)
    • operator= 때로는 효율성이 떨어지고 임시 객체가 필요할 수 있습니다.
    • 때때로 (인라인 함수의 경우) 옵티마이 저가 일부 / 모든 비 효율성을 제거 할 수 있음
  • 차례로 변수 범위를 최소화하면 범위에서 동시에 평균 변수 수가 최소화 됩니다 .

    • 그것은하게 쉽게 정신적으로 추적하는 범위에서 변수, 그 변수에 영향을 줄 수있는 실행 흐름과 문 및 가치의 수입을
    • 최소한 복잡하고 불투명 한 객체 의 경우 프로그램의 리소스 사용량 (힙, 스레드, 공유 메모리, 설명자) 이 줄어 듭니다.
  • 정의에서 변수 이름을 반복하지 않고 초기 의미있는 할당에서 때때로 더 간결합니다.

  • 참조와 같은 특정 유형 및 객체를 원할 때 필요 const

변수 정의 그룹화를위한 인수 :

  • 때로는 여러 변수 유형을 고려하는 것이 편리하고 간결 합니다.

    the_same_type v1, v2, v3;

    (이유가 유형 이름이 너무 길거나 복잡하기 때문에 typedef때로는 더 좋을 수도 있습니다)

  • 때로는 일부 작업에 관련된 변수 세트 및 유형을 강조하기 위해 사용법과 독립적으로 변수를 그룹화하는 것이 바람직합니다.

    type v1;
    type v2;
    type v3;

    이것은 유형의 공통성을 강조하고 복사 붙여 넣기, //주석 달기 등 을 용이하게하는 줄 당 변수를 고수하면서 변경하기가 조금 더 쉽습니다 .

프로그래밍의 경우와 마찬가지로 대부분의 상황에서 한 가지 실습에는 분명한 경험적 이점이있을 수 있지만, 다른 한 가지 실습은 실제로 몇 가지 경우보다 훨씬 더 나을 수 있습니다.