그것은되지 않는 포인터를 확인하는 것이 안전합니다 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은 매크로이기 때문에 실수로 다른 값으로 재정의한다고 가정하면.
답변
답변
그래 넌 할수있어. 값을 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_ptr
에Derived*
, 다음을 위해 사용 …”.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은 또한 심각한 장애 가능성이있을 때 (그리고 다른 많은 것들도 포함) 모나드를위한 특별한 도구를 가지고 있습니다. 그러나 이것은 그것들을 설명하는 장소가 아닙니다.
⟨/ 광고