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


171

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


13
진실은, 만약 당신이 명시 적 점검을 사용한다면, 0또는 에 대해 테스트하는 것만큼이나 효과적 nullptr입니다. ( NULLC'ism이며 헤더 파일을 포함해야합니다.)
cHao

5
@danijar 현대 C ++에서 nullptr을 사용할 수 있습니다.
SurvivalMachine

9
@cHao "C와의 호환성을 목표로"의 요점은 어디에 있습니까?
qdii

5
@danijar : 그렇습니다 . 모호한 동작을 제공 할 수있는 구현 종속 매크로 NULL이므로 C ++ 에서는 사용하지 않아야합니다 NULL.
Alok Save

3
이는 '만약'의 경우는 아니지만, 당신은 "NULL"과 "0"C ++의 포인터에 대한 피해야 이유에이 ideone 라이브 데모를 참조 ideone.com/tbvXNs
kfsone

답변:


197

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

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


42

예, 가능합니다.

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

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

4.12 부울 변환

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


29

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

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


10
포인터는 부울식이 아닙니다. 암시 적으로 변환됩니다. 이 전환을 기억해야 할 때 읽는 것이 더 낫다면 이해하는 것이 당신의 의견입니다. 코딩 스타일의 한 종류 일뿐입니다.
harper

7
@harper 코딩 스타일이라고 말할 수 있습니다. 그러나 정수도 부울이 아니기 때문에 동일한 논리를 if(som_integer)vs에 적용 할 수 있습니다 if(some_integer != 0). 나는 진술 을 피 0하거나 NULL진술하는 것을 선호 합니다.
Yu Hao

13
나는 그것이 코딩 스타일의 문제라는 데 동의합니다. 나는 if (pointer)나 자신 을 선호 if (ptr != nullptr)하게 되었지만 완벽하게 합법적 인 것 같습니다. 반면에, 내가 작성한 팀의 누군가를 if (some_integer)본다면 그것을로 바꿀 것 if (some_integer != 0)입니다. 그러나 나는 그것이 상대적으로 임의의 선호가 아닌 척하지는 않습니다. 포인터와 정수를 동일하게 취급하지 않는 것을 선호합니다.
Joel

1
@YuHao 그리고 그것은 코드 스타일이기 때문에 "좋아요"가 아니라 "좋아요"라고 말할 것입니다.
harper

5
@ franji1 그럼 if(isReady) if(filePtr) if(serviceNo)어때요? 이 경우 의도적으로 잘못된 변수 이름을 만드는 것은별로 의미가 없습니다. 어쨌든 나는 이미 당신의 요점을 알고 그것을 이해했지만 내 자신의 코딩 스타일을 직접 사용할 것을 주장 할 수 있습니다.
Yu Hao

13

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

난 항상 선호하는 것 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은 매크로이기 때문에 실수로 다른 값으로 재정의한다고 가정하면.

6
== 대신 =를 사용하면 사람들이 if (NULL == ptr)를 사용하지 않는 날에 거의 항상 컴파일러 경고가 생성됩니다.
paulm

@paulm 내가 요다 조건 이라고 불리는이 지점을 추가했기 때문에 일부 사람들은 읽기가 쉽지 않습니다.
Grijesh Chauhan

2
(boolean expression)? true : false완전히 무의미합니다. 이 표현은 ~로 평가 true된다 false; 당신이 말하는 것은 "사실이라면, 나에게 줘, 그것이 거짓이라면 나에게 줘"입니다. 간단히 말해서 부울 표현식 자체와 완전히 같습니다. 참고 node == NULL부울 식입니다. BTW, 두 구현은 서로 정확히 반대를 반환합니다. !=첫 번째 또는 !두 번째 중 하나만 원합니다 .
celtschk

BTW, =대신 가능한 하나의 보호는 가능할 때마다 ==변수를 만드는 것 const입니다. 예를 들어 함수를로 정의한 isEmnpy(node* const head) { ... }다음 실수로 node = NULL대신 쓰면 컴파일러에서 컴파일을 거부합니다 node == NULL. 물론 변경하지 않아도되는 변수에 대해서만 작동합니다.
celtschk

2
스마트 포인터 클래스를 가지고 있기 때문에 T* get() const대신 operator T*() const암시 적 변환을 방지 할 수 있습니다. 그러나 그들은 있습니다 operator bool() const.
StellarVortex

13

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

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


8

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


2

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

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

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

⟨/ 광고


1
나는이 질문에 실제로 대답하는이 간결한 규범에서 한 문장만을 볼 수 있습니다.
Lorne의 후작

@EJP : 당신은 ( "문자로 질문을하면 할 수 있습니다 내가 사용하는"), 다음은 (대답은 "예"단순히) 전혀 명시 적으로 대답 아니에요. 나는 OP 실제로 사용해야 if(ptr)하는 이유를 알기 위해 적절한 이유를 제시하려고 노력했습니다 if(ptr != nullptr).
leftaroundabout

1

예, 물론입니다! 사실 if (포인터)를 작성하는 것이 if (포인터! = NULL)보다 작성하는 것이 더 편리한 방법입니다. 1. 디버그하기 쉽고 2. 이해하기 쉽습니다. 또한 코드가 충돌하지 않습니다




-1

예, 내부 조건이 참일 때만 'IF'조건이 평가되므로 항상이 작업을 수행 할 수 있습니다. C에는 부울 리턴 유형이 없으므로 조건이 true이면 0이 아닌 값을 리턴하고 'IF'의 조건이 false로 나타날 때마다 0을 리턴합니다. 기본적으로 반환되는 0이 아닌 값은 1입니다. 따라서 코드를 작성하는 두 가지 방법은 정확하지만 항상 두 번째 방법을 선호합니다.


1
올바르게 기억하면 기본적으로 0이 아닌 값은 정의되어 있지 않습니다.
Lorne의 후작

-1

if-expression 을 다음과 같이 다시 쓸 수 있다면 경험의 법칙으로 생각합니다.

const bool local_predicate = *if-expression*;
if (local_predicate) ...

경고가 발생하지 않도록 if-expression 의 선호 스타일이어야합니다 . ( 포인터는 물론 오래된 C BOOL( #define BOOL int)를 C ++에 할당하면 경고가 표시됩니다 bool.)


-1

"안전 해요..?" 언어 표준과 생성 된 코드에 대한 질문입니다.

"좋은 습관입니까?" 이 문장의 독자적인 독자가 그 문장을 얼마나 잘 이해하는지에 대한 질문입니다. 이 질문을한다면, "안전한"버전은 미래의 독자와 작가에게 덜 명확하다는 것을 암시합니다.


내 의도는 그것이 안전한지 묻는 것이었다. 그래서 나는 그 말을 사용했습니다. 그러나 여기에 쓴 것은 질문에 대한 답변이 아닙니다. 대신 질문 아래에 의견이 있어야합니다. 그러면 답변을 삭제하고 질문 아래에 설명을 추가 할 수 있습니다.
danijar

@danijar StackOverflow를 처음 사용하고 성공하지 않고 '코멘트'섹션을 검색 한 것을 기억하십니까? 평판이 7 개인 사람은 그렇게 할 수 없습니다.
Broxzier

@JimBalter 다른 사람들이 볼 수 있기 때문에 매우 혼란 스럽습니다. 내가 SO를 처음 접했을 때 누군가 저를 그렇게 비난했습니다.
Broxzier

@ JimBalter 나는 살인과 도둑질하지 않습니다. 나는 danijar 에게 Fred Mitchell 이 새로운 사용자이고 의견을 게시 할 수 없다고 말하고 있었습니다 .
Broxzier

@JimBalter 오늘 시작했습니다. 또한 당신은 대신 이해하지 못하는 사람입니다. 그 의견은 이것의 혼란을지지하고 있습니다.
Broxzier
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.