일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- TwoBoneIK
- Kinematics
- c++
- C++11
- C++ #개발자 #Modern_C++ #스마트포인터 #Smart_Pointer #unique_ptr # shared_ptr # weak_ptr
- Override
- FABIK
- ComputerGraphics
- IKSolver
- 클래스
- final
- IK
- CCD
- ImageProcessing #ComputerGraphics #ComutationalPhotography #PoissinImageEditing #Siggraph2003
- InverseKinematics
- 상속
- FABRIK
- Modern C++
- Today
- Total
DevNote
Effective C++ Item3:: const를 적극 활용! review 본문
const
- 의미적인 제약 :: const 키워드가 붙은 객체는 외부 변경을 불가능하게 한다.
- 어떤 객체가 불변이어야 한다는 제작자의 의도를 컴파일러와 다른 개발자와 공유할 수 있는 수단
const의 특성
- 상수를 선언(정의)하는데 쓸 수 있다.
- static으로 선언한 객체에도 const를 붙일 수 있다.
- 어떠한 객체에도 붙을 수 있다. (객체 변수, 함수 파라미터 및 리턴 값, 멤버 함수, 포인터)
포인터와 const
- 포인터 자체를 상수로, 혹은 포인터가 가리키는 데이터를 상수로, 혹은 둘 다 상수로 지정할 수 있다.
다음의 내용은 아래의 예제를 통해 확인할 수 있다.
- 포인터가 가리키는 대상을 상수로 만들 때 const를 사용하는 스타일은 조금씩 다르다. 타입 앞에 cosnt가 붙을 수도 있고, 타입의 뒤쪽이자 *표 앞에 const를 붙일 수도 있다.
의미적인 차이는 전혀 없다. 아래의 함수를 통해 설명하자면,
void f1(const CTest* p); // f1은 상수 CTest 객체에 대한 포인터를 파라미터로 취한다
void f2(CTest const* p); // f2도 마찬가지
두 함수의 const 위치는 다르지만 내용적인 측면에서는 차이가 전혀 없다.
위의 구문은 눈에 익혀두는 게 좋다.
다만 아래의 경우와 혼동되서는 안된다.
void f3(CTest * const p);
iterator와 const
- 기본적으로 STL iterator의 동작원리는 T* 포인터와 비슷하다. 어떤 반복자를 const로 선언하는 것은 포인터를 상수로 선언하는 것과 같다.
T* const iter;
iterator는 자신이 가리키는 대상이 아닌 다른 것을 가리키는게 허용되지 않지만, 가리키는 대상 자체는 변경이 가능하다. 만약, 변경 불가능한 객체를 가리키는 iterator가 필요하다면 const_iterator를 쓴다.
아래의 예제는 const_iterator에 대한 것이다.
const T* iter;
함수와 const
가장 실용도가 높은 const의 쓰임새는 바로 함수 선에 쓸 경우다. 함수를 선언함에 있어서 cosnt는 함수 리턴 값, 파라미터, 멤버 함수 앞에 붙을 수도 있고, 함수 전체에 const의 성질을 부여할 수도 있다.
** 함수 리턴 값을 const로 지정하면, 안전성이나 효율을 포기하지 않고도 사용자 측의 에러 동발 상황을 줄일 수 있다.
아래의 두 예제는 다음과 같은 상황을 보여준다.
class CTest2
{ ... };
const CTest2 operator*(const CTest& lValue, const CTest& rValue);
위의 예제를 보면 굳이 operator*의 리턴 값이 상수일 필요가 있는지 의문이 들 수 있다. 그런데 상수 객체로 되어 있지 않으면 사용자 쪽에서 아래와 같이 실수를 저지를 수 있다.
CTest2 a, b, c;
...
(a * b) = c; // a*b의 결과에 operator=를 호출
두 수의 곱에 대입 연산을 취하고 싶은 개발자가 있을지는 모르겠지만, 이런 상황을 원하지 않았지만 무의식 중에 충분히 저지를 수 있는 실수이다. (bool로 implicit 형변환이 가능한 타입도 포함)
if(a * b = c) ... // 단순 비교를 의도하였으나...
위의 예제는 a와 b의 타입이 기본제공 타입이었다면 명백히 신택스 에러를 일으키는 코드지만, 사용자 정의 타입들의 특징 중 하나는 기본제공 타입과의 쓸데없는 비호환성을 피한다는 것인데, 위에서 본 바와 같이 두 수의 곱에 대해 대입 연산이 되도록 놓아두는 것이 바로 '쓸 데 없는' 경우가 됐다.
이 때! operator*의 리턴 값을 const로 정해두면 이런 경우를 미연에 방지할 수 있다.
*** 어떤 객체나 변수든 수정할 수 없게 하는 것이 목적이라면 const로 선언하는 것을 잊지 말자!
const 멤버 함수
멤버 함수에 const 키워드를 붙이면 다음과 같은 의미가 된다.
" 이 멤버 함수가 const 객체에 대해 호출될 함수다. "
얼핏 보기에는 의미가 와닿지도 이걸 왜 써야하는지도 의문이 들 수 있다. 그렇지만 그러한 의문에 대해 시원하게 내놓을 수 있는 대답은 두 가지다.
1) 클래스의 인터페이스를 쉽게 이해하도록 하기 위해서!
:: 그 클래스로 만들어진 객체를 변경할 수 있는 함수는 무엇이고, 변경할 수 없는 함수는 무엇인가를 사용자 쪽에서 알고 있어야 하는 것이다.
2) const 키워드를 통해 상수 객체를 사용할 수 있게! (Item 20과 연관됨)
:: C++프로그램의 실행 성능을 높이는 핵심 기법 중 하나가 객체 전달을 '상수 객체에 대한 참조자(reference-to-const)'로 진행하는 것이다.
=> 이 기법이 제대로 적용되려면, 상수 상태로 전달된 객체를 조작할 수 있는 const 멤버 함수가 준비되엉 있어야 한다는 것이 포인트이다.
'C++ > Effective' 카테고리의 다른 글
#define 대신 Inline (0) | 2020.03.11 |
---|