Effective C++ 22

[Effective C++] 항목 22: 데이터 멤버가 선언될 곳은 private 영역임을 명심하자

1. 개요이번 항목은 캡슐화의 중요성에 대해서 다시 한번 생각해보는 항목입니다. 기본적으로 데이터 멤버를 public으로 선언하면 안되는 이유와 그것이 protected에도 똑같이 적용된다는 점에 대해서 서술합니다. 2. public으로 선언하면 안되는 이유2-1. 문법적 일관성https://yeoul0714.tistory.com/59참고 [Effective C++] 항목 18: 인터페이스 설계는 제대로 쓰기엔 쉽게, 엉터리로 쓰기엔 어렵게 하자1. 개요 우리는 C++로 개발을 하면서 정말 수많은 인터페이스를 설계하게 됩니다. 그리고 우리가 개발한 인터페이스가 올바르게 쓰여지길 바랍니다. 만약 올바르게 쓰여지지 않았다면 최소한의yeoul0714.tistory.com 만약 데이터가 public이 아니라면 ..

[Effective C++] 항목 21: 함수에서 객체를 반환해야 할 경우에 참조자를 반환하려고 들지 말자

1. 개요우리는 항목 20에서 값에 의한 전달의 효율 문제에 대해서 공부했습니다. 그래서 우리는 기존 코드에서 값에 의한 전달이 있는 경우에 그것을 참지못하는 경우가 생기게 됩니다. 그러나 이것은 잘못된 마음가짐입니다. 이러다보면 실제로 있지도 않은 객체의 참조자를 넘기는 불상사를 만들어 내기도 합니다. 이러한 부분에 대해 자세히 설명해보고자 합니다. 2. 참조를 반환하는 것이 정답일까?2-1. 참조를 반환 시키는 법class Rational {public: Rational(int numerator = 0, int denominator = 1); private: int n, d; friend const Rational operator*(const Rational& lhs, cons..

[Effective C++] 항목 20: '값에 의한 전달'보다는 '상수객체 참조자에 의한 전달' 방식을 택하는 편이 대개 낫다

1. 개요C++에서는 함수로부터 객체를 받거나 함수에 객체를 전달할때 값에 의한 전달(pass-by-value)를 사용하기도 합니다. 특별한 경우가 아니면 함수의 매개변수는 실제 인자의 '사본'을 받게 됩니다. 그리고 호출한 쪽은 '사본'을 돌려받습니다. 여기서 이러한 사본을 만들어 내는 주체는 복사 생성자 입니다. 바로 이러한 점 때문에 값에 의한 전달의 비용이 매우 커지기도 합니다. 이번 항목은 이러한 주제를 바탕으로 참조자에 의한 전달을 권장하는 이유를 설명하는 항목입니다. 2. 값에 의한 전달이 비싼 이유class Person {public: Person(); // 간결함을 위해 매개변수 생략 virtual ~Person(); // virtual인 이유는 항목 7 확인 private: ..

[Effective C++] 항목 19: 클래스 설계는 타입 설계와 똑같이 취급하자

1. 개요C++에서 클래스를 설계하는 것은 새로운 타입을 만드는 것과 똑같습니다. 프로그래머는 클래스 설계자를 넘어 Type을 설계하는 막강한 힘을 가지고 있다는 것입니다. 언어 설계자가 기본 제공 타입을 만들때 만큼이나 큰 정성이 필요한 작업입니다 이번 항목은 클래스를 설계할때 깊게 고민해볼만 질문을 소개하는 항목입니다. 2. 질문2-1. 새로 정의한 타입의 객체 생성 및 소멸은 어떻게 이루어져야 하는가?이 부분에 따라서 생성자, 소멸자의 설계가 바뀌게 되고 메모리 할당, 해제 함수의 설계에도 큰 영향을 미칩니다. https://yeoul0714.tistory.com/35 [Effective C++] 항목 8: 예외가 소멸자를 떠나지 못하도록 붙들어 놓자1. 여러개의 예외는 처리가 곤란하다.만약 이러한..

[Effective C++] 항목 18: 인터페이스 설계는 제대로 쓰기엔 쉽게, 엉터리로 쓰기엔 어렵게 하자

1. 개요 우리는 C++로 개발을 하면서 정말 수많은 인터페이스를 설계하게 됩니다. 그리고 우리가 개발한 인터페이스가 올바르게 쓰여지길 바랍니다. 만약 올바르게 쓰여지지 않았다면 최소한의 항의의 몸부림이라도 보여주도록 설계해야 할것입니다. 어떤 인터페이스를 사용할 때 개발자의 의도대로 사용되지 않는다면 컴파일이 되지 않아야 옳고, 컴파일이 된다면 개발자의 의도대로 동작해야 할것입니다. 2. Wrapping하기개요에서 말한 상황이 나오려면 우리는 사용자가 할만한 실수들을 파악하고 있어야 합니다. 한가지 예시를 들어보도록 하겠습니다.class Date{public: Date(int month, int day, int year);} 이러한 클래스가 있다고 가정해보겠습니다. Date d(30,3,1955..

[Effective C++] 항목 17: new로 생성한 객체를 스마트 포인터에 저장하는 코드는 별도의 한 문장으로 만들자

1. 개요이번 장의 내용은 컴파일러마다 실행순서가 달라져서 발생하는 문제를 막는 방법에 대해 소개하는 항목입니다. 예를 들어보도록 하겠습니다.int Priority();void ProcessWidget(std::tr1::shared_ptr pw, int priority);이러한 함수 2개가 있다고 가정해 보겠습니다. 그리고 이렇게 만들어진 함수를 호출합니다. processWidget(new Widget, priority());일단 이것은 틀렸습니다. 왜냐하면 shared_ptr로 받고있기 때문에 자동으로 형변환이 안됩니다.(shared_ptr의 생성자는 explicit으로 선언되어 있습니다.) 그래서 아래와 같이 써야합니다.processWidget(std::tr1::shared_ptr(new Widge..

[Effective C++] 항목 16: new 및 delete를 사용할 때는 형태를 반드시 맞추자

1. 개요std::string *stringArray = new std::string[100];delete stringArray; 이 코드는 얼핏 보기에는 아무런 문제가 없어 보입니다. 메모리를 동적할당받고 잘 삭제해주고 있으니까요 그러나 이것은 완벽히 잘못된 코드입니다. 왜냐하면 동적할당으로 string객체를 100개만큼 생성해주고 있기 때문입니다. 위의 코드 처럼 한다면 1개의 객체 받게 해제시키지 못합니다. 2. new, delete의 동작방식new를 실행하면 2가지 동작이 수행됩니다. 1. 메모리가 할당됩니다.2. 할당된 메모리에 대해 한 개 이상의 생성자가 호출됩니다. ([]도 포함해서 그렇습니다.) delete도 비슷합니다. 1. 할당된 메모리에 대해 한개 이상의 소멸자가 호출됩니다.2. 메모..

[Effective C++] 항목 15: 자원 관리 클래스에서 관리되는 자원은 외부에서 접근할 수 있도록 하자

1. 개요자원 관리 클래스는 메모리 누수를 막는 아주 훌륭한 방법입니다. 그러나 우리는 종종 자원 관리 객체의 보호벽을 넘어서 실제 자원을 직접 만져야 할 일이 종종 생길것입니다. std::tr1::shared_ptr yptr(createYeoul());int YeoulAge(const Yeoul* ptr);int age = YeoulAge(yptr); // 에러 만약 코드를 이렇게 작성한다면 오류가 발생합니다. 왜냐하면 shared_ptr로 선언된 yptr과 Yeoul의 포인터는 형식이 맞지 않기 때문이지요 우리는 shared_ptr을 Yeoul*로 변환활 방법을 필요로 합니다. 2. 1번의 문제 해결법2-1. 명시적 형변환(explicit conversion)tr1::shared_ptr은 명시적으로 ..

[Effective C++] 항목 14: 자원 관리 클래스의 복사 동작에 대해 진지하게 고찰하자

1. 개요이번 항목은 자원관리 클래스를 만들때 복사 동작에 대해서 어떻게 처리해야할지를 다루는 문서입니다. 예를 하나 들어보도록 하겠습니다.void lock(Mutex* pm); // pm이 가리키는 mutex에 잠금을 겁니다.void unlock(Mutex* pm); //pm이 가리키는 mutex에 잠금을 풉니다. 이러한 mutex잠금을 관리하는 클래스를 만들려고 합니다. 이러한 클래스 역시 RAII 법칙을 따르게 됩니다. 생성시 자원을 획득하고 소멸 시에 자원을 해제하는 개념입니다. 아래는 이러한 클래스의 예제입니다.class Lock {public: explicit Lock(Mutex *pm) : mutexPtr(pm) { lock(mutexPtr); /..

[Effective C++] 항목 13: 자원 관리에는 객체가 그만!

1. 개요이번 장은 자원을 관리하는 법에 대해서 기술하는 챕터이다. 특히 항목 13은 포인터를 사용한뒤 해제하는 방법들을 소개한다. void f(){ Investment *pInv = createInvestment(); // 무언가 동작 delete pInv;} 이러한 코드를 보면 정상적으로 작동한다고 보일 수 있다. 그러나 중간에 있는 주석부분에 다양한 로직이 들어갈 수 있고 그때에 문제가 발생할 가능성이 있다. 2. 문제점과 auto_ptr저 코드가 정상적으로 delete까지 도달하면 아무런 문제가 없겠지만 그럴것이라는 보장이 절대 없다. 만약 중간에 다른 로직이 추가되어서 delete에 도달하기 전 return을 한다면 memory leak이 발생하게 된다. 혹은 예외등이 발생해..