문득, 파라미터를 참조형으로 보내는 코드와 포인터로 사용할 때 크게 구분하지 않고 사용했었다가 유지보수와 협업 측면에서 조금 더 생각하며 코딩을 하기로 결심했습니다.
1. 참조형을 사용하는 경우 (&)
참조형은 객체가 절대로 nullptr이 될 수 없을 때 사용합니다. 참조형은 간편하고 안전하며, 함수 내에서 해당 객체를 수정할 필요가 있는 경우 많이 사용됩니다.
사용할 때:
- 객체가 반드시 유효하고 nullptr일 가능성이 없는 경우.
- 함수 내부에서 객체를 수정할 가능성이 있을 때.
- 함수에서 호출 코드가 객체를 직접 소유하거나 관리하지 않음을 보장할 때.
- 객체의 주소를 다시 할당할 필요가 없는 경우.
void updateValue(MyClass &obj) {
obj.value = 10; // 객체 내용을 변경할 수 있음
}
장점:
- 포인터 연산이 필요 없으므로 가독성이 좋고 안전함.
- nullptr 체크가 필요 없으며, 코드가 간결해짐.
단점:
- 참조는 객체가 항상 존재해야 하므로 nullptr을 넘겨주거나, 없을 수 있는 경우에는 사용할 수 없음.
2. 포인터형을 사용하는 경우
포인터형은 객체가 유효하지 않을 가능성이 있을 때 사용합니다. 포인터를 사용하면, 객체가 nullptr일 수 있기 때문에 객체 존재 여부를 동적으로 확인할 수 있습니다.
사용할 때:
- 객체가 nullptr일 수 있는 경우. (즉, 함수 내에서 유효성을 검사할 필요가 있는 경우)
- 객체의 소유권을 함수에서 결정해야 하거나, 객체가 존재하지 않을 가능성이 있을 때.
- 객체의 주소를 변경하거나 다른 객체를 가리키도록 설정해야 할 때.
- 동적 할당 및 관리를 위해 사용해야 할 때.
void processObject(MyClass *obj) {
if (obj != nullptr) {
obj->value = 10; // 포인터로 객체 접근
}
}
장점:
- nullptr을 넘길 수 있어, 객체가 존재하지 않을 수 있는 경우를 표현할 수 있음.
- 동적 할당된 객체를 전달하고, 함수 내부에서 소유권을 전환하거나 삭제할 수 있음.
단점:
- 포인터 연산이 필요하므로, 잘못 사용 시 세그멘테이션 오류 발생 가능.
- nullptr 확인을 하지 않으면 잠재적인 오류가 발생할 수 있음.
3. 언제 참조형을 선택하고, 언제 포인터형을 선택할지
- 객체가 항상 유효해야 하며 존재가 보장될 경우: 참조형 사용.
- 객체가 선택적으로 필요할 때, 예를 들어, 객체가 없을 수 있는 경우(nullptr): 포인터형 사용.
- 함수 내에서 객체를 수정하거나 상태를 변경할 필요가 없는 경우에는 상수 참조(const &)를 사용하여 객체 복사를 피하고, 읽기 전용으로 접근할 수 있습니다.
- 함수가 객체의 소유권을 가지고 메모리를 해제해야 하는 경우에도 포인터형을 사용하여 동적 메모리 관리를 수행합니다.
void printValue(const MyClass &obj); // 읽기 전용, 객체가 반드시 유효
void modifyObject(MyClass &obj); // 객체를 수정하고, 항상 존재할 것으로 가정
void processOptional(MyClass *obj); // 객체가 nullptr일 수 있는 경우
void transferOwnership(MyClass *obj); // 객체 소유권을 함수에서 관리
참조형(&)은 안전하고 가독성이 좋으며 객체가 항상 유효할 때 사용하고, 포인터형(*)은 유연성과 객체 유효성 검사를 위한 도구로서, 객체가 nullptr일 수 있거나, 동적으로 관리되는 객체를 다룰 때 적합합니다.
'C++ STL, 알고리즘' 카테고리의 다른 글
구조적 바인딩 c++ (0) | 2024.10.14 |
---|---|
참조형 & (0) | 2024.10.07 |
c++ 구조적 바인딩 (0) | 2024.10.07 |
++i vs i++ 누가 일반적인가. (0) | 2024.10.07 |
Optional Type (0) | 2024.10.07 |