일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
Tags
- 언리얼
- 함수 객체
- 참조자
- Smart Pointer
- c++
- 반복자
- lua
- 게임
- 메타테이블
- 예외
- effective stl
- 루아
- virtual function
- 상속
- operator new
- implicit conversion
- Effective c++
- 스마트 포인터
- 영화 리뷰
- 티스토리챌린지
- 암시적 변환
- 비교 함수 객체
- reference
- 오블완
- resource management class
- exception
- UE4
- 영화
- more effective c++
- 다형성
Archives
- Today
- Total
스토리텔링 개발자
[Effective C++] 11. operator= 자기 대입 문제 본문
728x90
항목 11. operator = 에서는 자기 대입에 대한 처리가 빠지지 않도록 하자
자기 대입
- 자기 자신에 대해 대입 연산자를 적용하는 것.
자기 대입에 대한 처리가 필요한 이유
- 중복 참조 때문에 자기 대입이 생길 수 있다.
-
int i = 1; int& ci1 = i; int& ci2 = i; ci1 = ci2; // 중복참조로 인한 자기대입
-
- 같은 타입 객체 여럿을 참조자 / 포인터로 사용하는 코드를 작성할 때는 같은 객체가 사용될 가능성을 고려해야 한다.
자기 대입 문제의 예시
class Bitmap { ... };
class Widget
{
private:
Bitmap* pb;
};
Widget& Widget::operator=(const Widget& rhs)
{
delete pb;
pb = new Bitmap(*rhs.pb); // &rhs와 this가 같을 경우 rhs.pb 역시 삭제되어 버린다!
return *this;
}
- 매개변수로 넘어온 객체가 자기 자신일 경우(자기 대입일 경우) pb가 삭제된 상태로 남아버리는 문제가 있다.
처리법
- 일치성 검사
-
Widget& Widget::operator=(const Widget& rhs) { if(this == &rhs) return *this; // 객체가 같은지 검사 delete pb; pb = new Bitmap(*rhs.pb); return *this; }
- 예외에 안전하지 못할 수 있다.
- new Bitmap 표현식에서 예외가 터지면 Widget 객체의 pb는 결국 삭제된 Bitmap을 가리키는 포인터로 남게 된다.
-
- 더 나은 방법 : 문장 순서 조정
-
Widget& Widget::operator=(const Widget& rhs) { Bitmap* pOrig = pb; pb = new Bitmap(*rhs.pb); delete pOrig; // 원래의 pb를 기억해뒀다가 삭제 return &this; }
- 이제 new Bitmap에서 예외가 발생해도 pb는 기존 상태를 유지하므로 예외에 안전하다.
-
- 또 다른 방법 : 복사 후 맞바꾸기(copy and swap)
-
class Widget{ void swap(Widget& rhs); // 스왑 기능 }; Widget& Widget::operator=(const Widget& rhs) { Widget temp(rhs); swap(temp); // rhs의 사본과 *this의 데이터를 스왑 return *this; }
- 이는 C++의 아래 두 가지 특징을 활용해서 조금 다르게 구현할 수 있다.
- 클래스의 복사 대입 연산자는 인자를 참조가 아니라 값으로 취하도록 선언할 수 있다.
- 값에 의한 전달을 수행하면 전달된 대상의 사본이 생긴다.
-
Widget& Widget::operator=(widget rhs) { swap(rhs); return *this; }
- 가독성이 떨어지지만, 객체 복사 코드가 함수 본문에서 매개변수의 생성자로 옮겨졌으므로 컴파일러가 더 효율적인 코드를 생성할 여지가 있다.
-
728x90
'개발 > Effective C++' 카테고리의 다른 글
[Effective C++] 13. 자원 관리 객체(RAII) (0) | 2024.06.03 |
---|---|
[Effective C++] 12. 복사 함수 구현 (0) | 2024.05.31 |
[Effective C++] 10. operator= 반환값 (0) | 2024.05.29 |
[Effective C++] 9. 객체 생성 / 소멸 중 가상 함수 호출 문제 (0) | 2024.05.23 |
[Effective C++] 8. 소멸자 호출 중 예외 문제 (0) | 2024.05.22 |
Comments