[c++] if (포인터! = NULL) 대신 if (포인터)를 사용할 수 있습니까?

그것은되지 않는 포인터를 확인하는 것이 안전합니다 NULL간단하게 작성하여 if(pointer)또는 내가 사용해야합니까 if(pointer != NULL)?



답변

당신은 할 수 있습니다; 널 포인터는 내재적으로 부울 false로 변환되고 널이 아닌 포인터는 true로 변환됩니다. C ++ 11 표준에서 부울 변환 섹션에서 :

산술, 범위가 지정되지 않은 열거 형, 포인터 또는 멤버 형식에 대한 포인터의 전가는 유형의 전가로 변환 될 수 있습니다
bool. 0 값, 널 포인터 값 또는 널 멤버 포인터 값은로 변환됩니다
false. 다른 값은로 변환됩니다
true
. 유형의 prvalue는 유형의 prvalue
std::nullptr_t
로 변환 될 수 있습니다
bool
. 결과 값은
false
입니다.


답변

예, 가능합니다.

  • 널 포인터는 내재적으로 false로 변환됩니다.
  • 널이 아닌 포인터는 true로 변환됩니다.

이것은 부울 변환 절에 해당하는 C ++ 표준 변환의 일부입니다 .

4.12 부울 변환

산술, 범위가 지정되지 않은 열거 형, pointer 또는 멤버 유형에 대한 포인터의 값은 bool 유형의 prvalue로 변환 될 수 있습니다. 0 값, 널 포인터 값 또는 널 멤버 포인터 값은 false로 변환됩니다. 다른 값은 true로 변환됩니다. std :: nullptr_t 유형의 prvalue는 bool 유형의 prvalue로 변환 될 수 있습니다. 결과 값은 false입니다.


답변

그래 넌 할수있어. 사실, if(pointer)익숙해지면 읽고 쓰는 것이 더 간단하기 때문에 사용하는 것을 선호 합니다.

또한 C ++ 11 nullptr이 더 선호 된다는 점에 유의하십시오 NULL.


답변

질문에 대한 답변이 있지만 포인트를 추가하고 싶습니다.

난 항상 선호하는 것 if(pointer)대신 if(pointer != NULL)하고 if(!pointer)대신 if(pointer == NULL):

  • 간단하고 작습니다
  • 적은 기회는 내가 평등 체크 연산자를 맞춤법이 틀린 경우 가정, 버그가 코드를 작성 ==하여 =
    if(pointer == NULL)맞춤법이 틀린 할 수 있습니다 if(pointer = NULL)내가 그것을 피할 그래서 최고의 단지입니다 if(pointer).
    (나는 또한 하나의 대답으로 일부 요다 조건을 제안 했지만 그것은 다른 문제입니다)

  • 마찬가지로 while (node != NULL && node->data == key), 나는 while (node && node->data == key)나에게 더 분명한 것을 쓸 것이다 (단락을 사용하는 것을 보여줌).

  • (멍청한 이유 일 수 있습니다) NULL은 매크로이기 때문에 실수로 다른 값으로 재정의한다고 가정하면.

답변

명시 적으로 NULL을 검사하면 컴파일러가 수행하려는 작업에 대한 힌트를 제공하여 오류가 덜 발생합니다.

여기에 이미지 설명을 입력하십시오


답변

그래 넌 할수있어. 값을 0과 비교하는 기능은 암시 적으로 C에서 상속되었으며 모든 버전의 C ++에 있습니다. if (!pointer)NULL에 대한 포인터를 확인 하는 데 사용할 수도 있습니다 .


답변

널 포인터의 관련 사용 사례는 다음과 같습니다.

  • 존재하지 않거나 아직 연결되지 않은 더 깊은 트리 노드로 리디렉션 그것은 항상 헌신적 인 클래스에서 밀접하게 캡슐화 해야하는 것이므로 가독성이나 간결성은 그다지 문제가되지 않습니다.
  • 다이나믹 캐스트. 특정 파생 클래스 포인터에 기본 클래스 포인터를 캐스트하면 (다시 피하려고하지만 때때로 필요할 수도 있음) 항상 성공하지만 파생 클래스가 일치하지 않으면 널 포인터가됩니다. 이것을 확인하는 한 가지 방법은

    Derived* derived_ptr = dynamic_cast<Derived*>(base_ptr);
    if(derived_ptr != nullptr) { ... }

    (또는 바람직하게는 auto derived_ptr = ...). 이제 이것은 안전 보호 if블록의 범위 밖에 (유효하지 않은, 즉 null) 파생 포인터를 남겨두기 때문에 좋지 않습니다 . C ++을 사용하면 부울 변환 가능 변수 if-condition 내에 도입 할 수 있으므로 필요하지 않습니다 .

    if(auto derived_ptr = dynamic_cast<Derived*>(base_ptr)) { ... }

    더 짧고 범위가 안전 할뿐만 아니라 의도가 훨씬 더 명확합니다. 별도의 if 조건에서 null을 검사 할 때 독자는 “좋습니다. derived_ptr여기서 null이 아니어야합니다 … 글쎄, 왜 그런 것입니까?” null입니까? ” 한 줄 버전이 매우 분명하게 말한다 반면 “당신이 안전하게 캐스트 할 수있는 경우 base_ptrDerived*, 다음을 위해 사용 …”.

    IMO는 일반적으로 이것을 피해야하지만 포인터를 반환하는 다른 가능한 실패 작업에도 동일하게 작동합니다. 포인터가 boost::optional아닌 작업 실패의 결과에 대해 “컨테이너” 와 같은 것을 사용하는 것이 좋습니다 .

널 포인터의 주요 사용 사례는 항상 암시 적 캐스트 스타일의 변화에 작성해야한다면, 나는에 일관성 이유로 그것의 좋은 말하고 싶지만 항상 내가 옹호 것 즉,이 스타일을 사용하는 if(ptr)동안 if(ptr!=nullptr).


나는 광고로 끝내야 할 것을 두려워합니다. if(auto bla = ...)구문은 실제로 그러한 문제 에 대한 실제 솔루션에 약간의 성가신 근사치입니다 : 패턴 일치 . 왜 먼저 (포인터 캐스팅과 같은) 어떤 행동을 강요하고 실패가 있다고 생각합니까? 마치 음식이 있고 수프를 만들고 싶어하는 것과 같습니다. 주스가 부드러운 채소 인 경우 주스 추출 작업을 통해 조수에게 전달합니다. 먼저 보지 마십시오. 감자를 먹었을 때 여전히 조수에게 먹이를 주지만 실패 메모와 함께 얼굴에 다시 때립니다. 아, 명령형 프로그래밍!

훨씬 낫습니다. 발생할 수있는 모든 사례를 즉시 고려하십시오. 그런 다음 그에 따라 행동하십시오. 하스켈 :

makeSoupOf :: Foodstuff -> Liquid
makeSoupOf p@(Potato{..}) = mash (boil p) <> water
makeSoupOf vegetable
 | isSoft vegetable  = squeeze vegetable <> salt
makeSoupOf stuff  = boil (throwIn (water<>salt) stuff)

Haskell은 또한 심각한 장애 가능성이있을 때 (그리고 다른 많은 것들도 포함) 모나드를위한 특별한 도구를 가지고 있습니다. 그러나 이것은 그것들을 설명하는 장소가 아닙니다.

⟨/ 광고