Effective c++ 14

[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++] 항목 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++] 항목 11: operator=에서는 자기대입에 대한 처리가 빠지지 않도록 하자

1. 개요자기대입은 어떤 객체가 자기 자신에게 대입 연산을 실행하는 것을 말합니다. 예를 들면 이런것이죠 Yeoul y; y=y; 문법상 아무 문제가 없는 코드입니다. a[i] = a[j]; i와j가 같아지면 자기대입이 됩니다. *pa = *pb; 둘이 가리키는 대상이 같으면 자기대입이 됩니다. 이러한 경우가 생기는 이유는 하나의 객체를 여러곳에서 참조하는 중복참조 상태 때문입니다. 이럴땐 같은 객체가 사용될 가능성을 고려하는것이 바람직한 자세입니다. void DoSomething(const Base& rb, Derived* pd);// 사실 rb와 *pb는 같은 객체였을지도 모릅니다. 결론은 자기 대입 연산은 생각보다 빈번하게 발생할 수 있다는 것이지요 2. 발생하는 문제들/해결법 2-1. 문제1자기대..

[Effective C++] 항목 10: 대입 연산자는 *this의 참조자를 반환하게 하자

1. 개요C++의 대입 연산자는 여러개가 동시에 엮일 수 있습니다. 무슨말인가 하면 우리는 일반적으로 대입연산자를 a=3; 이런식으로 씁니다. 그러나 a=b=c=3; 이런식으로 쓰는것도 가능하다는 말입니다. 우측 부터 연산이 진행되는 연산자입니다. 위의 연산을 괄호를 쳐서 본다면 이렇게 됩니다. a=(b=(c=3)); c에 3대입되고 그 결과가 b에 대입되고 다시 그 결과가 a에 대입됩니다. 이러한 연산이 가능하려면 연산자가 좌변에 대한 참조자를 반환하도록 구현되어 있어야 합니다.2. 다른것들은?좌변 객체의 참조자를 반환하자는 규칙은 = 뿐만 아니라 다른 경우에도 지켜져야 합니다. 예를들면 += -= *= 등과같은 연산고 *this를 반환하게 하는것이 관례입니다. 이 관례는 모든 기본제공 타입들이 따..

[Effective C++] 항목 9: 객체 생성 및 소멸 과정 중에는 절대로 가상 함수를 호출하지 말자

1. 개요저자는 객체 생성, 소멸중에 가상 함수를 절대 호출하지 말라고 합니다. 그 이유는 무엇일까? 지금부터 알아 보도록 합시다. 2. 문제아래 코드를 보면 Transaction이 가장 최상위 클래스이고 하위로 BuyTransaction, SellTransaction이 각각 Transaction을 상속받고 있는 상태입니다. main에서는 BuyTransaciton의 객체를 만들어 주고 있습니다. BuyTransaction객체를 만들기 위해서는 부모 클래스의 생성자가 먼저 호출되야 합니다. 그렇게 부모클래스인 Transaction의 생성자가 호출되는데 여기서 문제가 발생합니다. 왜냐하면 Transaction의 생성자에서는 logTransaction이라는 가상함수를 호출중이기 때문입니다. 여기서 호출되는..

[Effective C++] 항목 8: 예외가 소멸자를 떠나지 못하도록 붙들어 놓자

1. 여러개의 예외는 처리가 곤란하다.만약 이러한 클래스가 있고 벡터에서 10개의 Yeoul객체를 가지고 있다고 생각해보자.class Yeoul{public: ~Yeoul(){}};void DoSomething(){ std::vectorv;} 벡터 v가 소멸될때에 벡터는 자신이 들고있던 Yeoul객체들을 소멸시켜야 할 책임을 가지고 있습니다. 만약에 첫번째 Yeoul객체를 소멸하던중 예외가 생겼다고 생각해봅시다. 나머지 9개의 객체도 소멸되어야함으로 벡터는 여전히 나머지 객체에 대해서 소멸자를 호출하게 됩니다. 그런데 두번째 Yeoul객체 역시 예외를 발생시키면 어떻게 될까요? 이렇게 예외가 2개이상이 되어버리면 C++에서 감당하기 어렵습니다. 이러한 동작의 원인은 바로 예외가 터지는 것을 내..

[Effective C++] 항목 7: 다형성을 가진 기본 클래스에서는 소멸자를 반드시 가상 소멸자로 선언하자

1. 부모 클래스 소멸자를 virtual로 해야하는 이유우리는 기본 클래스의 소멸자는 반드시 virtual로 선언해주어야 합니다. 아래 예시를 통해서 그 이유를 알아보도록 합시다.// Effective C++ 항목 7: 다형성을 위한 기초 클래스에서는 소멸자를 virtual로 선언하자#include class GameEntity {public: // 문제: 가상 소멸자가 없음 ~GameEntity() { std::cout createGameEntity()에서 반환되는 값들은 전부 heap에 있게 됨으로 결국엔 delete를 통해 메모리를 해제해 주어야 합니다. 그러나 이렇게 되면 PlayerCharacter의 소멸자는 호출되지 않게 됩니다. 그이유는 1. createGameEntity가 반환..

[Effective C++] 항목 6: 컴파일러가 만들어낸 함수가 필요 없으면 확실히 이들의 사용을 금해 버리자

1. 개요블로그의 주인장인 여울은 게임을 사랑하는 개발자이다. 여울은 게임을 소개하는 프로그램을 만들었데 이 프로그램에는 게임을 나타내는 클래스가 있다.class Game {}; 그런데 이세상에 똑같은 게임이 존재할까요? 아닙니다. 똑같은 게임은 없고 모든 게임은 각자의 이름이 있고 각자의 플레이 방식이 있습니다. 즉 Game객체는 복사본을 만드는 것이 이치에 맞지 않습니다. 그래서 Game이랑 객체 자체를 복사시도를 하면 컴파일이 되지 않았으면 합니다. Game MapleStory;Game BattleGround;Game StarCraft(MapleStory); // 복사를 막아주세요!!MapleStory = BattleGround; // 복사를 막아주세요!! 프로그래머가 어떠한 기능이 수행되기를 ..