본문 바로가기

서적 정리/Effective C++56

28.내부에서 사용하는 객체에 대한 "핸들"을 반환하는 코드는 되도록 피하자 클래스를 설계할 때 메모리 부담을 최소화 하고 싶다고 생각하고 고민한다. 사각형은 꼭짓점 두 개로 표현할 수 있다. 꼭짓점 두 개를 갖는 사각형 클래스를 구현한다고 생각했을 때 지금까지 책에서 봤던 것들을 기반으로 클래스를 설계 한다면 class Point { public: Point(int x, int y) : x(x), y(y) { } void SetX(int newVal) { x = newVal; } void SetY(int newVal) { y = newVal; } private: int x, y; }; struct RectData { Point ulp; //upper left point 좌측 상단 Point lrp; //lower right point 우측 하단 }; class Rectangle.. 2021. 12. 19.
27.캐스팅은 절약, 또 절약! 잊지 말자 C 스타일의 캐스팅 방식은 두 가지가 있다. (type) 표현식 //(int)a type(표현식) //int(a) C++ 스타일의 캐스팅 방식은 네 가지가 있다. const_cast(표현식) //const_cast(a) dynamic_cast(표현식) //dynamic_cast(a) reinterpret_cast(표현식) //reinterpret_cast(a) static_cast(표현식) //static_cast(a) const_cast : 객체의 상수성(const)을 붙이거나 없애는 용도로 사용한다. 사실상 상수성을 붙이는건 선언만 하기 때문에 없애는 용도로만 사용한다. dynamic_cast : 안전한 다운캐스팅(safe downcasting)을 할 때 사용한다. 주어진 객체가 어떤 클래스 상속 계.. 2021. 12. 17.
26.변수 정의는 늦출 수 있는 데까지 늦추는 근성을 발휘하자 변수를 정의하면 생성자와 소멸자가 호출되는 비용은 피해갈수 없다. 사용하지 않는 변수를 정의했을 때도 당연히 비용을 지출하는데, 이런 비용은 의미없는 비용이니 피해야한다. 비밀번호가 충분히 길 경우 해당 비밀번호를 암호화하여 반환하는 함수가 있다. string encryptPassword(const string& password) { string encrypted; size_t minimumPasswordLength = 10; if (password.length() < minimumPasswordLength) throw logic_error("Password is too short"); ... return encrypted; } 비밀번호가 너무 짧으면 logic_error타입(54장 참고)의 예외를 던지.. 2021. 12. 17.
25.예외를 던지지 않는 swap에 대한 지원도 생각해 보자 STL에서도 swap은 구현되어있고, 만약 나보고 swap을 구현하라고 하면 십중팔구 임시 객체를 생성하여 구현할 것이다. template void Swap(T& a, T& b) { T temp(a); a = b; b = temp; } 물론 기본제공 타입같은 경우엔 xor-swap이란 꼼수도 존재하긴 한다. a = a ^ b; b = a ^ b; a = a ^ b; 표준 라이브러리에서 제공하는 swap은 구현 코드를 보면 복사만 제대로 지원하는 타입이기만 하면 어떤 객체든 swap이 가능하다. 하지만 뭔가 불합리함이 느껴지긴하다. swap 한 번하는데 복사가 3번이나 일어나고 있다. 복사하면 손해를 보는 타입들 중 대표를 뽑는다면 다른 타입의 실제 데이터를 가리키는 포인터다. 쉽게 말해서 다른 객체의 데.. 2021. 12. 16.
24.타입 변환이 모든 매개변수에 대해 적용되어야 한다면 비멤버 함수를 선언하자 사실 나는 게임 프로그래밍 위주였기 때문에 이번 챕터에서 말하는 상황을 마주한적은 없었다. 지금까지 그저 DX라이브러리 사용자였기 때문이다. 하지만 최근 STL를 구현하면서 vector나 list를 구현하면서 operator를 구현할 일이 생겼는데 이런 생각을 해본적이 없었기에 이런일이 발생할 수 있구나 하면서 코드를 다시 보게 됐다. 어느 한 클래스에 대해서 operator를 구현할 때 암시적 변환이 일어나는 경우가 있다. class Rational //Rational : 유리수 { public: Rational(int num = 0, int den = 1) : n(num), d(den) { } ~Rational() {} int numerator() const { return n; } int denom.. 2021. 12. 15.
23.멤버 함수보다는 비멤버 비프렌드 함수와 더 가까워지자. 객체 지향 법칙은 할 수 있는 만큼 데이터를 캡슐화하라고 한다. 솔직히 제목을 보고 무슨 개소리를 하는거지 싶다. 어차피 객체에 대한 함수일텐데 왜 객체 밖에다가 만들라는 거지? 캡슐화랑 무슨 관련이 있단 소리지 싶다. 웹브라우저를 나타내는 클라스가 있다고 가정해보자. 이 클라스에 캐시를 비우는 함수, 방문한 URL의 기록을 지우는 함수, 쿠키를 제거하는 함수가 있을 것이다. 그리고 이 세가지를 동시에 하는 멤버 함수를 구현할 수도 있다. class WebBrowser { public: void clearCach(); //캐시 삭제 void clearHistory(); //URL 삭제 void removeCookies(); //쿠키 삭제 void clearEverything() //캐시, URL, 쿠키 .. 2021. 12. 14.
22.데이터 멤버가 선언될 곳은 private 영역임을 명심하자 솔직히 당연한 소리다. private에 선언함 으로써 캡슐화를 하기 때문이고 무엇보다 멤버 데이터를 누구나 손댈 수 있다면 프로그램에 무슨일이 생길지 어느 누구도 예측할 수가 없다. 만약 어떤 클래스의 공개 인터페이스에 있는 것들이 전부 함수뿐이라면, 그 클래스의 멤버에 접근하고 싶을 때 괄호를 무조건 붙여야 할 것이다. 무조건 괄호를 붙임으로써 문법적 일관성이 지켜진다. 어떤 데이터 멤버를 public으로 선언했다면 모두가 이 데이터에 대해 읽기 및 쓰기 접근권한을 갖게 되지만, 이 값을 읽고 쓰는 함수가 있으면, 접근 불가, 읽기 전용, 읽기 쓰기 접근을 구현할 수 있다. 내가 많이 쓰는 방법이다. class AccessLevels { public: int GetReadWrite() const { r.. 2021. 12. 14.
21.함수에서 객체를 반환해야 할 경우에 참조자를 반환하려고 들지 말자 참조자는 이름일 뿐이다. 존재하는 객체에 붙는 다른 이름이다. 즉, 참조자는 어떤 것에 대한 또 다른 이름이어야 하니 반드시 존재해야 한다(나는 이 성질을 이용하여 매개변수에 참조자를 쓰고 있다. 포인터와 다르게 NULL값이 들어가면 안되기에 편함). 함수 수준에서 새로운 객체를 만드는 방법은 두 가지뿐이다. 1.스택에서 생성(지역 변수) 2.힙에서 생성(동적 할당) 아래와 같은 클래스가 있다고 가정하자 class Rational { public: Rational(int numerator = 0, int denominator = 1); private: int n, d; friend const Rational& operator*(const Rational& lhs, const Rational& rhs); .. 2021. 12. 14.
20.'값에 의한 전달'보다는 '상수객체 참조자에 의한 전달' 방식을 택하는 편이 대개 낫다 C++는 기본적으로 함수로부터 객체를 전달받거나 함수에 객체를 전달할 때는 값에 의한 전달방식(pass-by-value)을 사용한다. C에서 물려받은 특성중 하나이다. 특별히 다른 방식을 지정하지 않는 한, 함수 매개변수는 실제 인자의 사본을 통해 초기화 되며, 어떤 함수를 호출한 쪽은 그 함수가 반환한 값의 사본을 돌려받는다. 이 사본을 만들어내는 원천이 복사 생성자이다. 이 점에 의해 값에 의한 전달이 고비용의 연산이 되기도 한다. class Person { public: Person(); virtual ~Person(); private: string name; string address; }; class Student : public Person { public: Student(); ~Student.. 2021. 12. 14.