전체 글
[Effective C++] 52. 위치지정 new를 작성한다면 위치지정 delete도 같이 준비하자
[Effective C++] 52. 위치지정 new를 작성한다면 위치지정 delete도 같이 준비하자
2022.07.24new 표현식을 사용했을 때 호출되는 두 가지 함수 Widget * pw = new Widget; 위에서는 함수 두 개가 호출된다. 우선 메모리 할당을 위해 operator new가 호출되고, 그 뒤를 이어 Widget의 기본 생성자가 호출된다. 여기서 첫 번째 함수 호출은 무사히 지나갔는데 두 번째 함수 호출이 진행되다가 예외가 발생했다고 가정해보자. 이렇게 사고가 났을 경우 첫 단계에서 이미 끝난 메모리 할당을 취소해야 한다. 왜냐하면 메모리 누수가 발생하기 때문이다. 하지만 Widget 생성자에서 예외가 튀어나오면 pw에 포인터가 대입될 일은 절대로 안 생기기 때문에 사용자 코드에서는 이 메모리를 해제할 수 없다. 따라서 이 메모리의 해제는 C++ 런타임 시스템이 맡아줘야 한다. C++ 런타임 시스..
[Effective C++] 51. new 및 delete를 작성할 때 따라야 할 기존의 관례를 잘 알아 두자
[Effective C++] 51. new 및 delete를 작성할 때 따라야 할 기존의 관례를 잘 알아 두자
2022.07.23operator new의 기본 요구사항 1. 반환 값이 제대로 되어있어야 한다. 요청된 메모리를 마련할 수 있는 경우 반환 값은 메모리에 대한 포인터이다. 요청된 메모리를 마련할 수 없는 경우 bad_alloc 타입의 예외를 던진다. 2. 가용 메모리가 부족할 경우에는 new 처리자 함수를 호출해야 한다. 3. 크기가 없는 메모리 요청(0바이트)에 대한 대비책을 갖춰두어야 한다. 4. 기본 형태의 new가 가려지지 않도록 한다. 비멤버 버전의 operator new 함수 의사 코드 operator new 멤버 함수는 파생 클래스 쪽으로 상속이 되는 함수이다. // 다른 매개변수를 추가로 가질 수 있다. void * operator new(std::size_t) throw(std::bac_alloc) { ..
[Effective C++] 50. new 및 delete를 언제 바꿔야 좋은 소리를 들을지 파악해 두자
[Effective C++] 50. new 및 delete를 언제 바꿔야 좋은 소리를 들을지 파악해 두자
2022.07.16일반적으로 컴파일러가 제공하는 operator new, operator delete는 대체로 쓸만하다. 그리고 사용자가 오버로딩을 통해 재정의한다면 수동으로 지정해줄 관례들이 있다. 따라서 기본 operator의 new와 delete를 사용해도 무관하지만 사용자가 본인의 프로젝트에 알맞은 오버로딩을 구현한다면 훨씬 효율적인 operator new , operator delete가 탄생할 수도 있는데 언제 operator new, delete를 바꾸어야 하는 지 알아보자. 사용자 정의 new와 delete를 고려해야 할 때 1. 잘못된 힙 사용을 탐지하기 위해 new 한 메모리에 delete 하는 것을 잊어버리면 메모리 누출이 되고, 이미 메모리 해제한 메모리를 또 메모리 해제한다면 프로그램은 터질 것이다..
[Effective C++] 49. new 처리자의 동작 원리를 제대로 이해하자
[Effective C++] 49. new 처리자의 동작 원리를 제대로 이해하자
2022.07.16메모리 할당 과정 operator new는 메모리 할당이라는 임무를 맡고 있으며, 임무 실패 시 예외를 발생시킨다. 하지만, 예외를 던지기 전 사용자 에러 처리 함수를 선 호출하도록 설계되어있는데, 이 에러 처리 함수를 가리켜 new 처리자(new-handler, 할당 에러 처리자)라고 한다. 이와 같은 메모리 고갈 상황을 처리할 함수를 사용자 쪽에서 지정할 수 있도록 표준 라이브러리에서는 set_new_handler라는 함수가 준비되어있다. 이 함수는 에 선언되어 있다. namespace std { typedef void (*new_handler)(); new_handler set_new_handler(new_handler p) throw(); } new_handler는 받는 것도 없고 반환하는 것도 ..
[Effective C++] 48. 템플릿 메타프로그래밍, 하지 않겠는가?
[Effective C++] 48. 템플릿 메타프로그래밍, 하지 않겠는가?
2022.07.16템플릿 메타프로그래밍이란? 컴파일 도중에 실행되는 템플릿 기반의 프로그램을 작성하는 일을 뜻한다. TMP 프로그램이 실행을 마친 후엔 그 결과로 나온 템플릿으로부터 인스턴스화 된 C++ 소스코드가 다시 보통의 컴파일 과정을 거치는 것이다. 템플릿 메타프로그래밍(TMP)의 장점 1. TMP를 쓰면 다른 방법으로는 까다롭거나 불가능한 일을 쉽게 할 수 있다. 2. 템플릿 메타프로그램은 C++ 컴파일이 진행되는 동안에 실행되기 때문에, 기존 작업을 런타임 영역에서 컴파일 타임 영역으로 전환할 수 있다. 런타임 영역을 컴파일 타임 영역으로 끌고 오기 때문에 실행 도중 터졌던 문제를 컴파일 도중에 찾을 수 있다. 또한, 컴파일 타임에 동작을 다 하기 때문에 실행 코드가 작아지고, 실행 시간도 짧아지며, 메모리도 ..
[Effective C++] 47. 타입에 대한 정보가 필요하다면 특성정보 클래스를 사용하자
[Effective C++] 47. 타입에 대한 정보가 필요하다면 특성정보 클래스를 사용하자
2022.07.15STL은 컨테이너, 반복자, 알고리즘의 템플릿으로 구성되어 있지만, 이 외에 유틸리티라고 불리는 템플릿도 몇 개 들어있다. 이들 중 하나가 advance라는 템플릿인데, 이 템플릿의 역할은 반복자를 지정된 거리만큼 이동시키는 것이다. template void advance(IterT& iter, DistT d); // iter를 d 단위만큼 전진시킨다. d= 0) { while(d--) ++iter; } else { while(d++) --iter; } } } 위 코드가 제대로 되려면 iter타입인 IterT가 임의 접근 반복자 타입인지를 알아야 하는데, 이를 위해서 컴파일 도중 어떤 주어진 타입의 정보를 얻을 수 있게 하는 객체인 특성정보(traits)를 사용한다. 특성정보(traits) 특성정보는 컴..
[Effective C++] 46. 타입 변환이 바람직할 경우에는 비멤버 함수를 클래스 템플릿 안에 정의해 두자
[Effective C++] 46. 타입 변환이 바람직할 경우에는 비멤버 함수를 클래스 템플릿 안에 정의해 두자
2022.07.15모든 매개변수에 대해 암시적 타입 변환이 되도록 만들기 위해서는 비멤버 함수를 사용해야 한다. 템플릿화 한 Rational 클래스 template class Rational { public: Rational(const T& num = 0, const T& deno = 1) : numerator(num), denominator(deno) {} const T Numerator() const { return numerator; } const T Denominator() const { return denominator; } private: T numerator; T denominator; }; template const Rational operator*(const Rational& lhs, const Ratio..
[Effective C++] 43. 템플릿으로 만들어진 기본 클래스 안의 이름에 접근하는 방법을 알아 두자
[Effective C++] 43. 템플릿으로 만들어진 기본 클래스 안의 이름에 접근하는 방법을 알아 두자
2022.07.08템플릿 클래스를 기본 클래스로 파생 시키는 클래스를 구현 할 상황이 생겼다고 가정해보자. class CompanyA { public: void SendClearText(const string& msg); void SendEncrypted(const string& msg); }; class CompanyB { void SendClearText(const string& msg); void SendEncrypted(const string& msg); }; class MsgInfo {}; template class MsgSender { public: void SendClear(const MsgInfo& info) { string msg; Company c; c.SendClearText(msg); //암시적 인터..
[Effective C++] 42. typename의 두 가지 의미를 제대로 파악하자
[Effective C++] 42. typename의 두 가지 의미를 제대로 파악하자
2022.07.08C++에서 템플릿 매개변수의 경우 class와 typename은 완전히 같은 의미이다. template class Widget; template class Widget; 의존이름(dependent name) vs 비의존 이름(non-dependent name) template void print2nd(const C& container) { if (container.size() >= 2) { C::const_iterator iter(container.begin()); ++iter; int value = *iter; cout
[Effective C++] 41. 템플릿 프로그래밍의 천릿길도 암시적 인터페이스와 컴파일 타입 다형성부터
[Effective C++] 41. 템플릿 프로그래밍의 천릿길도 암시적 인터페이스와 컴파일 타입 다형성부터
2022.07.08클래스의 특성 객체 지향 프로그래밍을 이루는 축은 명시적 인터페이스와 런타임 다형성이다. class Widget { public: Widget(); virtual ~Widget(); virtual size_t size() const; virtual void normalize(); void swap(Widget& other); }; void Func(Widget& w) { if(w.size() > 10) { Widget temp(w); temp.normalize(); temp.swap(w); } } 명시적 인터페이스 Func 함수의 매개변수인 w는 Widget 클래스의 객체이므로 w는 Widget 인터페이스를 지원해야 한다. 이 인터페이스를 소스코드(Widget 클래스가 있는 헤더파일 등)에서 찾으면 확인..
[Effective C++] 40. 다중 상속은 심사숙고해서 사용하자
[Effective C++] 40. 다중 상속은 심사숙고해서 사용하자
2022.07.03다중 상속의 의미 둘 이상의 클래스로부터 상속을 받는 것 다중 상속의 문제점 함수 호출의 모호성 둘 이상의 기본 클래스로부터 똑같은 이름(함수, typedef 등)을 물려받을 가능성이 생긴다는 점이다. 즉, 모호성이 생긴다는 것인데 아래의 예제를 봐보자. class BorrowableItem { public: void checkOut(); ... }; class ElectronicGadget { private: bool checkOut() const; ... }; class MP3Player:public BorrowableItem, public ElectronicGadget {...}; MP3Player mp; mp.checkOut(); // 모호성 발생! 이것은 중복된 함수 호출 중 하나를 골라내는 C..
[Effective C++] 39. private 상속은 심사숙고해서 구사하자
[Effective C++] 39. private 상속은 심사숙고해서 구사하자
2022.07.03private 상속 public 상속은 is-a관계로 나타낸다. 이 관계는 Student가 Person으로부터 public 상속으로 파생된 상태의 클래스 계통이 주어지면 함수 호출을 성공시키기 위해 컴파일러가 Student를 Person으로 암시적 변환을 수행하는 예를 통해 잘 설명이 된다.(항목 32 참고) 그럼 private 상속은 뭘 의미하는 것일까? class Person {...}; class Student: private Person {...}; // private 상속 void eat(const Person& p); void study(const Student& s); Person p; Student s; eat(p); // OK eat(s); // Error, Student는 Person의..