Ch 07. 포인터 - 05. nullptr

2025. 4. 15. 20:14Programming Language/C++

반응형

1. null 포인터

null 포인터어떤 것도 가리키지 않는 포인터를 말한다

포인터는 원래 어떤 메모리 주소를 저장하는 변수인데 null 포인터는 의미 있는 주소가 없다는 걸 표현하기 위해 특별히 설정된 값이다.

아직 유효한 대상을 할당받지 않은 상태 또는 더 이상 유효하지 않은 상태를 나타낸다.

 

2. null 포인터는 왜 필요할까

기존에 포인터의 경우는 값을 초기화 해주지 않으면 

이렇게 초기화 되지 않은 포인터를 사용하고 있다고 에러를 띄운다.

 

그런데 때로는 포인터가 아직 어떤 것도 가리키지 않거나, 가리킬 수 없는 상태가 필요하다.

 

1) 어떤걸 가리킬지 대상을 모를때

Student* p = nullptr;  // 아직 대상이 없음

// 나중에 조건에 따라 할당
if (조건) {
    p = new Student;
}

포인터는 선언했으나 로직에 따라 어떤 객체를 가리킬지가 다르게 결정되기에 초기 상태를 안전하게 지정하기 위해서 nullptr이 필요하다.

 

2) 리턴값이 실패하거나 없음(null 리턴)

Student* findStudentById(int id) {
    if (id == -1) return nullptr;  // 못 찾았음
    return new Student;
}

함수의 반환 값이 포인터이고 이 함수를 사용해서 

Student * sptr = findStudentById(10);

이렇게 포인터에 넣어줄텐데 return을 nullptr로 하지 않은 경우 값이 반환되지 않으면 해당 포인터는 쓰레기 값이 들어가면서 에러가 발생할 가능성이 있기에 이 함수의 반환 값으로 어떤것도 받지 못했다면 그 포인터는 아무것도 가리키지 않는 값으로 설정해줘야 좀 더 안정적으로 사용이 가능하다.

또한 리턴값으로 nullptr을 쓰면, 찾았는지 여부, 유효성을 명확히 알 수 있다는 점도 사용의 이유가 된다.

 

3) 포인터가 해제되어 뎅글링 포인터가 될 수 있는 경우

Student* p = new Student;
delete p;
p = nullptr;  // dangling pointer 방지

이렇게 포인터가 동적할당된 구조체를 가리키고 있다가 delete를 통해서 해제를 하면 p 는 쓰레기 값을 가리키고 있게 되면서 뎅글링 포인터가 될 수 있다.

그렇기에 해제되는 시점 바로 직후에 nullptr을 넣어줌으로써 잘못된 사용으로 에러를 발생하는 것을 막을 수 있고 

if (p != nullptr){
   ...
}

 이런 조건문을 통해서 내가 사용하려는 함수가 이미 해제 된 함수인지 체크해가며 잘못된 접근 자체를 방지할 수도 있게 된다.

 

 

4) 조건으로 분기해서 어떤 객체가 유효한지 파악하기 위해

위에서 사용한 잘못된 접근 방지에서 사용했던것과 같이

if (studentPtr != nullptr) {
    studentPtr->study();
} else {
    std::cout << "학생 정보 없음" << std::endl;
}

이렇게 nullptr이라는 값으로 조건을 맞춰 해당 포인터가 아무것도 가리키지 않는 상태라면 잘못된 접근을 우회하여 방지할 수 도 있게 된다.

 

3. null 포인터의 사용법

널 포인터의 경우는 그냥 간단하게 포인터에 대입하여 사용하면 된다.

이러면 컴파일을 하더라도 에러를 발생시키지 않고 널포인터의 값을 출력한다.

 

물론 이렇게 널포인터로 할당한 경우에는 * 역참조 연산자를 사용해서 접근해서는 안된다.

결과 또한 

이렇게 이상하게 종료되는 것을 알 수 있다.

반응형