이번 항목은 디버깅에 있어 정말 난해한 자동 변환에 대해서 알아본다. 자동 변환은 사용자 입장(함수들..)에선 편하지만, 구현자 입장(프로그래머)에서 보면 정말 염두해야 한다. 그 이유를 알아보자. 표준 C++ string 은 const char*로의 어떠한 암시적 변환을 가지지 않는다. 다음 코드를 보면 정말 필요할 듯 한데 말이다. #include int main( void ) { std::string s1( "hello" ), s2( "world" ); strcmp( s1, s2 ); // 에러 strcmp( s1.c_str(), s2.c_str() ); // 성공 return 0; } 이 코드의 에러 나는 부분에서 알아서 형 const char* 형태로 변환되면 얼마나 좋을까? 어챂 const c..
책 정리 검색 결과
두 개의 포인터가 같은 객체를 가리키고 있는지 그 판단을 하기 위한 알고리즘을 제시하는 항목이다. 다음의 코드 this != &others 검사는 자기 할당을 피하기 위한 기본 방법이다. 과연 이 조건절만으로 자기 할당을 피하는게 가능할까? 그렇지 않은 경우와 어떻게 고칠 수 있는지 알고리즘을 만들라. T& T::operator=( const T& other ) { if( this != &other ) { /* ... 처리 세부 사항 ....*/ } return this*; } 문제 : 정말로 이것으로 자기 참조를 피할수 있을까? 피할수 없다면 어떻게 고칠 수 있을까? 고칠 수 있다면 그 알고리즘은 어떻게 만들어 졌는가? 나는 이 항목을 시작하기 전에 한가지 생각에 빠지게 되었다. "자기 대입이 왜 나뻐..
갑작 스러운 질문 부터 시작한다. 자원을 단순히 관리하고 마지막 try/catch 구문을 덤으로 제거할 수 있는 좀 더 진보적인 기술들을 어떻게 적용할 수 있을까? 내재된 데이터형 T의 요구사항을 줄여서 Stack을 개선할 수 있는 방법이 있을까? 일반적인 컨테이너에서 예외 설계를 사용할 수 있을까? new[]와 delete[]가 정말로 하는 일은 무엇일까? 지금까지 만들어본 Stack 의 주요 예외안전성을 메모리를 관리하는 방법에 그 초점을 두고 있다. 따라서, 이런것만 따로 관리하는 보조클래스를 한쪽에 두는것이 좋을 듯 싶다. 다음 코드를 이런 초점에 맞추어서 만들어진 클래스이다. template class StackImpl { /* ? ? ? ? ? */ StackImpl( size_t size =..
8항목 9항목 10학목까지 오면서 익혔던 개념들에 대하여, 정리를 해 보는 코너이다. 1. 중요한 예외 안전에 관한 보증은 무엇인가? 2. 막 구현한 Stack에서, 포함하는 T의 필수사항은 무엇인가? 답 1. 답이라고 할것 까진 없지만, 의미상 그렇다는 뜻이다. (Effective C++ 을 보게 되면, 정리된것이 나와 있으니 자세한것은 그것을 참고 하도록) 기본 보증 : 예외가 있어도 Stack 개체의 자원에 피해가 가지 않는다. 강한 보증 : 예외에 의해 연산이 중단되도, 프로그램 상태는 바뀌지 않는다. 완벽 보증 : 어떠한 상황에서도 예외를 발생시키지 않는다. 아무리 못해도 기본 보증은 있어야 된다고 본다. 2. T::T 기본 생성자 T::T(const T& rhs) 복사 생성자 T& T::ope..
극강 난이도 9½ 이다. 기본 생성자와 소멸자, 복사 할당자와 복사 생성자를 만들었다면, 이제 스택의 인터페이스를 만들어야 된다. 지금까지 한것들을 간축하게 정리하게 되면 template class Stack { public: Stack(); ~Stack(); Stack( const Stack& ); // 복사 생성자 Stack& operator=( const Stack& ); // 복사 할당자 private: T* v_; // T의 vsize_를 위해 size_t vsize_; // 충분히 큰 메모리를 가리키는 size_t vused_; // 포인터 T의 실제 사용 개수 }; 문제 : Count(), Push(), 그리고 Pop()를 예외에 안전하도록 작성해 보도록 하자. Count( ) templat..
다시 Stack 템플릿 클래스를 가져 온다. template class Stack { public: Stack(); ~Stack(); Stack( const Stack&); // 복사 생성자 Stack& operator=(const Stack&);// 복사 할당자 /* .... */ private: T* v_; // T의 'vsize_'를 위해 충분히 size_t vsize_; // 큰 메모리를 가리키는 포인터 size_t vused_; // T의 실제 사용 개수 }; 문제 : 이제 예외에 안전한 복사 생성자와 복사 할당자를 만들어 보아라. 곰곰히 생각해 보면 복사 생성자와 복사 할당자는 서로 같은 로직이 들어 갈 수 밖에 없을 것이다.( 왜냐하면, 복사된다는 전제가 똑같이 깔리기 때문이다,) 그래서 복..
최근댓글