SlideShare une entreprise Scribd logo
1  sur  64
자원 관리
NHN NEXT 장문익
resource
 사용을 일단 마치고 난 후엔 시스템에 돌려주어야 하는 모든 것
 가져와서 다 썻으면 해제해야, 즉 놓아 주어야 한다.
 동적 할당 메모리(메모리를 할당하고서 해제하지 않으면 memory leak)
자원을 항상 해제되도록 하는 방법
 자원을 객체에 넣고
 그 자원 해제를 소멸자가 맡도록 하며,
 그 소멸자가 반드시 호출되도록 만든다.
auto_ptr
 포인터와 비슷하게 동작하는 객체(smart
pointer)
 가리키고 있는 대상에 대해 소멸자가 자동으
로 delete를 불러주도록 설계되어 있다.
 한 객체를 동시에 둘이 가리킬 수 없다. 복사생
성하거나 대입하면 한 auto_ptr은 null이 된다.
std::auto_ptr<Investment>(createInvestment
());
자원 관리에 객체를 사용하는 방법1
 자원을 획득한 후에 자원 관리 객체에 넘긴다.
 자원 획득 즉 초기화(Resource Acquisition is Initialization:RAII)
 자원 획득과 자원 관리 객체의 초기화가 한 문장에서 이루어 진다.
자원 관리에 객체를 사용하는 방법2
 자원 관리 객체는 자신의 소멸자를 사용해서 자원이 확실히 해제되도록 한다.
 소멸자는 어떤 객체가 소멸될 때 자동적으로 호출되므로 실행 제어가 어떤 경위로 블록을 떠나는가
에 상관없이 자원 해제가 제대로 이루어지게 된다.
auto_ptr의 특성
std::auto_ptr<Investment>pInv1(creteInvestment());
std::auto_ptr<Investment>pInv2(pInv1); // pInv2가 가리지는 객체는 pInv1이 가리키는 객체
// pInv1은 null, auto_ptr의 특성
pInv1 = pInv2 // pInv1는 객체를 가리키고, pInv2는 null
auto_ptr가 답인가?
 복사 동작이 이루어지면 이전의 것은 null이 된다.
 auto_ptr가 관리하는 객체는 두개 이상의 auto_ptr가 물고 있으면 안 된다.
 이 두 가지 특성때문에 동적으로 할당되는 모든 자원에 대한 관리 객체로서 auto_ptr를 쓰는 것은
최선이 아닌 듯하다.
참조 카운팅 방식 스마트 포인터
 reference-counting smart pointer(RCSP)
 특정한 어떤 자원을 가리키는 외부 객체의 개
수를 유지하고 있다가 그 개수가 0이 되면 해
당 자원으로 삭제하는 스마트 포인터
 garbage collection 방식과 유사
 std::tr1::shared_ptr<Investment>pInv(crea
teInvestment());
reference-counting smart pointer의 특성
std::tr1::shared_ptr<Investment>pInv1(createInvestment());
std::tr1::shared_ptr<Investment>pInv1(pInv2); // auto_ptr과 달리 pInv1, pInv2가
// 동시에 객체를 가리킬 수 있다.
pInv1 = pInv2; // 변화없음
auto_ptr, tr1::shared_ptr의 공통 특성
 소멸자 내부에서 delete 연산자를 사용한다.
 delete [] 연산자가 아니다.
 즉, 동적 할당한 배열에 auto_ptr, tr1::shared_ptr을 사용하면 안 된다.
std::auto_ptr<std::string>aps(new std::string[10]); // error
std::tr1::shared_ptr<int> spi(new int[1024]);; // error
RAII 객체가 복사될 때 어떻게 해야하나?
 복사를 금지한다.
class Lock : private Uncopyable {
public :
…
};
RAII 객체가 복사될 때 어떻게 해야하나?
 관리하고 있는 자원에 대해 참조 카운팅을 수행한다.
 자원을 사용하고 있는 마지막 객체가 소멸될 때까지 그 자원을 해제하면 안 되는 경우
 tr1::shared_ptr를 이용?
 tr1::shared_ptr를 참조 카운트가 0이 될 때 자신이 가리키고 있던 대상을 삭제하도록 되어있기 때문
에 안 된다.
 tr1:shared_ptr는 „삭제자(delete)‟ 지정을 허용한다.
shared_ptr 삭제자 활용
class Lock {
public :
explicit Lock(Mutex *pm) // shared_ptr를 초기화하는데, 가리킬 포인터로
: mutexPtr(pm, unlock // Mutex 객체의 포인터를 사용하고 삭제자로 unlock 함수를 사용
{
lock(mutexPtr.get());
)
private :
std::tr1::shared_ptr<Mutex>mutexPtr;
}
RAII 객체가 복사될 때 어떻게 해야하나?
 관리하고 있는 자원을 진짜로 복사한다.
 깊은 복사(deep copy)
RAII 객체가 복사될 때 어떻게 해야하나?
 관리하고 있는 자원의 소유권을 옮긴다.
명시적 변환(explicit conversion)
 tr1::shared_ptr 및 auto_ptr은 명시적 변환을 수행하는 get이라는 멤버 함수를 제공한다.
 get 함수를 사용하면 각 타입으로 만든 스마트 포인터 객체에 들어있는 실제 포인터를 얻어낸다.
std::tr1::shared_ptr<Investment> pInv(createInvestment());
int daysHeld(const Investment *pi);
// int days = daysHeld(pInv); // error
int days = daysHeld(pInv.get());
자원 접근과 명시적, 암시적 변환
 안전성만 따지만 명시적 변환이 대체적으로 낫다.
 하지만 사용자 편의성을 놓고 보면 암시적 변환이 괜찮다.
 “맞게 쓰기에는 쉽게, 틀리게 쓰기에는 어렵게“
new
 메모리가 할당된다.
 할당된 메모리에 대해 한 개 이상의 생성자가 호출된다.
delete
 기존에 할당된 메모리에 대해 한 개 이상의 소멸자가 호출된다.
 그 후에 그 메모리가 해제된다.
객체 배열 delete
st::string *stringPtr1 = new std::string;
st::string *stringPtr1 = new std::string[100];
…
delete stringPtr1;
delete [] stringPtr2;
typedef std::string AddressLines[4];
std::string *pal = new AddressLines
// delete pal;
delete [] pal;
new로 생성한 객체는 스마트 포인터로…
int priority();
void processWidget(std::tr1::shared_ptr<Widget> pw, int priority);
// processWidget(new Widget, priority()); error!
processWidget(std::tr1::shared_ptr<Widget>(new Widget), priority());
std::tr1::shared_ptr의 생성자는 explicit로 선언되어 있기 때문에 „new Widget‟표현식에 의해 만들어
진 포인터가 tr1::shared_ptr 타입의 객체로 바꾸는 암시적인 변환이 없다.
매개변수 호출 순서에 따른 위험성
processWidget(std::tr1::shared_ptr<Widget>(new Widget), priority());
연산이 실행되는 순서
priority -> “new Widget” -> tr1::shared_ptr?
반드시 위의 순서대로 되지는 않는다.
priority가 몇 번째로 호출될지는 모른다.
문제는 priority 호출부분에서 error가 발생하면 “new Widget”으로 만들었던 포인터가 유실될 수 있다.
해결책
std::tr1::shared_ptr<Widget> pw(new widget); // new로 생성한 객체를 스마트 포인터에
processWidget(pw, priority()); // prority 호출에 문제가 발생해도 포인터 유실 없음
// memory leak 방지
그래서 new로 생성한 객체를 스마트 포인터로 넣는 코드는 별도의 한 문장을 만들어야 한다.
설계 및 선언
제대로 쓰기 쉽게, 엉터리로 쓰기 어렵게
class Date {
public :
Date(int month, int day, int year);
…
};
Date d(30, 3, 1995); // 월, 일이 바뀜
Date d(3, 40, 1955); // 일이 이상한 값
struct Day {
explicit Day(int d) : val (d) {}
int val;
};
class Date {
public:
Date(const Month& m, const Day& d,
const Year& y);
…
};
Date d(30, 3, 1955) // 자료형이 틀렸다.
Date d(Day(30), Month(3), Year(1995));
// 자료형이 틀렸다.
Date d(Month(3), Day(30), Year(1995));
Investment * createInvestment();
std::tr1::shared_ptr<Investment>createInvestment();
반환값이 shared_ptr이라는 것을 사용자가 알 수 있게 한다.
이 객체를 삭체하는 것을 깜빡하고 넘어가더라도 share_ptr가 알아서 해제한다.
tr1::shared_ptr의 특성 이용1
 생성 시점에 자원 해제 함수(„삭제자„)를 엮을 수 있다.
std::tr1::shared_ptr<Investment>pInv(0, getRidOfInvestment); // error
std::tr1::shared_ptr<Investment*>pInv(static_cast<Investment*>)(0), getRidOfInvestmentl
// 0은 int, tr1::share_ptr가 요구하는 것은 Investmet* 타입의 실제 포인터이기 때문에 static_cast
tr1::shared_ptr의 특성 이용2
 교차 DLL 문제 해결
 객체 생성 시에 어떤 동적 링크 라이브러리의 new를 썼는데 그 객체를 삭제할 때는 이전의 DLL과
다른 DLL에 있는 delete를 섰을 경우
 tr1::shared_ptr의 기본 삭제자는 tr1::shared_ptr이 생성된 DLL과 동일한 DLL에서 delete를 사용하
도록 만들어져 있다.
좋은 클래스 설계
 새로 정의한 타입의 객체 생성 및 소멸은 어떻게 이루어져야 하는가?
 객체 초기화는 객체 대입과 어떻게 달라야 하는가?
 새로운 타입으로 만든 객체가 값에 의해 전달되는 경우에 어떤 의미를 줄 것인가?
 새로운 타입이 가질 수 있는 적법한 값에 대한 제약은 무엇으로 잡을 것인가?
 기존의 클래스 상속 계통망에 맞출 것인가?
 어떤 종류의 타입 변환을 허용할 것인가? (implicity, explicit)
 어떤 연산자와 함수를 두어야 의미가 있을까?
좋은 클래스 설계
 표준 함수들 중 어떤 것을 허용하지 말 것인가?
 새로운 타입의 멤버에 대한 접근권한은 어느 쪽에 줄 것인가?
 „선언되지 않은 인터페이스‟로 무엇을 둘 것인가?
 새로 만드는 타입이 얼마나 일반적인가?
 정말로 필요한 타입인가?
pass_by_value?
class Person {
public :
Person();
virtual ~ Person();
…
private :
std::string name;
std::string address;
};
class Student : public Person {
public :
Student();
~Student();
…
private:
std::string schoolName;
std::string schoolAddress;
};
pass-by-value? 비용이 너무 크다.
bool validateStudent(Student s);
Student plato;
bool platoIsOK = validateStudent(plato);
 plato로부터 매개변수 s 초기화시키기 위해
Sudent 복사 생성자 호출
 s는 validateStudent가 복귀할 때 소멸
 결국, 복사 생성자 1번, 소멸자 1번
 Student객체가 생성될 때마다 string 객체 2개
생성
 Student객체는 Person객체 파생이므로
Person 생성, string 객체 2개 생성
 소멸도 생성과 마찬가지…
reference-to-const
 호출에 따르는 비용을 줄일 수 있다.
bool validateStudent(const Student& s); // 새로 만들어지는 객체 같은 것이 없기 때문에
// 생성자와 소멸자가 전혀 호출되지 않는다.
// const로 전달된 student 객체를 보호
복사손실 문제(slicing problem)
class Window {
public:
…
std::string name() const;
virtual void display() const;
};
class WindowWithScrollBars : public Window {
public:
…
virtual void display() const;
};
void printNameAndDisplay(Window s)
{
std::cout << w.name();
w.display();
}
WindowWithScrollBars wwsb;
printNameAndDisplay(wwsb);
복사손실 문제
 매개변수 w 생성된다.
 하지만 매개변수가 Windows 객체이므로, 이 객체를 상속받은 WindowWithScrollBars 객체의 고유
정보들은 손실된다.
 결국, 호출하는 display()함수도 Windows 객체의 것이다.
복사손실 문제 해결
void printNameAndDisplay(const Windows& w)
{
std::coutn << w.name();
w.display();
}
w를 참조자로 전달하면 w는 어떤 종류의 윈도우가 넘겨지더라고 그 윈도우의 성질을 갖게 된다.
함수에서 객체 반환할때 참조자 반환하지말자
class Rational {
public :
Rational(int numerator = 0, int denominator = 1);
…
private :
int n, d;
friend
const Rational
operator*(const Rational& lhs, const Rational rhs);
};
Rational a(1, 2);
Rational b(3, 5);
Rational c = a * b; // 객체가 생성되지 않았는데 참조자를 반환하고 있다.
스택을 이용한 객체 반환
cosnt Rational& operation*(const Rational& lhs, const Rational& rhs)
{
Rational result(lhs.n * rhs.n, lhs.d * rhs.d); // 생성자를 호출
retrun result; // result는 지역객체으로 함수가 끝날 때 소멸됨에도 불구하고 참조자를 반환
}
힙을 이용한 객체 반환
const Rational& operator*(const Rational& lhs, const Rational& rhs)
{
Rational *result = new Rational(lhs.n * rhs.n, lhs.d * rhs.d); // 생성자 호출, delete 부담
return *result;
}
static을 이용한 객체 반환
const Rational& operator*(const Rational& lhs, const Rational& rhs)
{
static Rational result; // 반환할 참조자가 가리킬 정적객체
result = …;
return result;
}
정적객체는 공유하는 값이므로 활용에 제한이 있을 뿐더러, 스레디 안전성 문제도 있다.
객체를 반환하는 올바른 방법
inline const Rational operator*(const Rational& 1hs, const Rational& rhs)
{
return Rational(lhs.n * rhs.n, lhs,d * rsh.d);
}
새로운 객체를 반환하게 만드는 것이 정도이다.
데이터 멤버가 선언될 곳은 private
 private으로 선언하면 데이터 멤버에 접근하기 위해서 멤버 함수를 써야 한다.
 어떤 데이터 멤버는 public이고, 어떤 데이터 멤버는 private이라면 일관성이 사라진다.
 함수를 통해서만 데이터 멤버에 접근할 수 있도록 구현해 두면, 데이터 멤버를 나중에 계산식으로
대체할 수 있을 것이다.(캡슐화, encapsulation)
 public 데이터 멤버가 있고, 이것을 제거한다고 가정해보자. 캡슐화가 얼마나 중요한지 알 수 있다.
 protected도 마찬가지로 안전하지 않다.
 결국은 캡슐화를 고려하였을 때, 데이터 멤버는 private에 선언하는 것이 답이다.
멤버함수보다는 비멤버 비프렌드 함수
class WebBrowser {
public:
…
void clearCache();
void clearHistory();
void removeCookies();
}
class WebBrowser {
public:
…
void clearEverything(); // clearCache,
// clearHistory,
// removeCookies
…
};
비멤버 버전
void clearBrowser (WebBrowser& wb)
{
wb.clearCache();
wb.clearHistory();
wb.removeCookies();
}
멤버 버전이 좋을까? 비멤버 버전이 좋을까?
비멤버 버전의 장점
 캡슐화
 피키징 유연성(packaging flexibility)가 높아진다.
 컴파일 의존도도 낮춘다.
 확장성이 높아진다.
 결국, 비멤버 방법이 멤버 함수보다 여러모로 낫다.
namespace를 활용한 비멤버 함수
namespace WebBrowserStuff {
class WebBrowser {…};
void clearBrowser {WebBrowser& wb};
…
}
namesapce를 활용한 비멤버 함수의 장점
 namespace는 class와 달리 여러 개의 소스 파일에 나뉘어 흩어질 수 있다.
 다시 말해, 필요할 때 기능을 불러다 쓰면 된다. WebBrowser객체가 없어도 쓸 수 있다.
 응용도가 높은 편의 함수들과 응용도가 낮은 편의 함수를 구분하여 관리하면 컴파일 의존성에서 비
교적 자유로울 수 있다.
 클래스 멤버 함수로 사용하게 되면 기능을 쪼개는 것이 불가능하다.
 편의 함수 전체를 여러 개의 헤더 파일에(그러나 하나의 namespace) 나누어 놓으면 편의 함수 집
합의 확장도 쉬워진다. 해당 네임스페이스에 비멤버 비프렌드 함수를 추가하면 끝.
타입변환이 모든 매개변수에 적용된다면 비멤버 함수로
// 유리수를 나타내는 클래스
class Rational {
public:
Rational(int numerator = 0, int denominator = 1);
int numerator() const;
int denominator() const;
const Rational operator*(const Rational& rhs) const;
private:
…
};
Rational oneEighth(1, 8);
Rational oneHalf(1, 2);
Rational result = oneHalf * oneEighth; // OK
result = result * oneEighth; // OK
result = oneHalf * 2; // OK
result = 2 * oneHalf; // error
result = oneHalf.operator*(2); // OK
result = 2.operator*(oneHalf); // error
암시적 타입 변환에 대해 매개변수가 먹혀들려면
매개변수 리스트에 들어있어야 한다.
암시적 변환을 가능하게 하기위해서
class Rational {
…
};
const Rational operator*(const Rational& lhs, const Rational& rhs) // 비멤버 함수로 만들었다.
{ // 모든 인자에 대해 암시적 타입 변환
return Raional(lhs.numerator() * rhs.numerator(), lhs.denominator() * rhs.denominator());
}
Rational oneFourth(1, 4);
Rational result;
result = oneFourth * 2;
result = 2 * oneFourth;
예외를 던지지 않는 swap
// 표준 라이브러리에서 제공하는 swap
namespce std {
template<typename T>
void swap(T& a, T& b)
{
T temp(a);
a = b;
b = temp;
}
}
pimpl 관용구
class Widget Impl {
public :
…
private :
int a, b, c;
std::vector<double> V;
…
};
class Widget {
public :
Widget (const Widget& rhs);
Widget& operator = (const Widget& rhs)
{
…
*pImpl = *(rhs.pImpl);
…
}
…
private :
WidgetImpl *pImpl;
};
표준 swap 알고리즘의 빈틈
 위의 Widget 객체를 직접 맞바꾼다면? pImpl포인터만 바꾸는 것이 아니다.
 Widget 객체 세 개를 복사하고, WidgetImpl 객체 세 개도 복사한다.
 비효율적이다.
std::swap 특수화
namespace std {
template<> // 완전 템플릿 특수화를 컴파일러에게 알려 준다.
void swap<Widget>(Widget& a, Widget& b)
{
swap(a.pImpl, b.pImpl);
}
}
class Widget {
public :
…
void swap(Widget& other)
{
using std::swap;
swap(pImpl, other.pImpl);
}
…
};
namespace std {
template<>
void swap<Widget>(Widget& a, Widget& b)
{
a.swap(b);
}
}
함수는 부분 특수화가 되지 않는다.
// Widget이 클래스가 아닌 클래스 템플릿
template<typename T>
class WidgetImpl {…};
template<typename T>
class Widget {…};
namespace std {
template<typename T>
void swap<Widget<T>>(Widget<T>& a,
Widget<T>& b)
{ a.swap(b); }
}
위 코드는 적법하지 않다.
C++은 클래스 템플릿의 부분 특수화는 인정
함수 템플릿에 대해서는 허용하지 않는다.
함수 템플릿의 부분적 특수화는 오버로드
namespace std {
template<typename T>
void swap(Widget<T>& a,
Widget<T>& b)
{ a.swap(b) };
}
위의 코드는 유효하지 않다.
 std 내의 템플릿에 대한 완전 특수화는 OK
 std에 새로운 템플릿을 추가하는 것은 OK 아
님
템플릿 전용 버전으로 만들자
namespace WidgetStuff {
…
template<typename T>
class Widget {…};
…
template<typename T> // 비멤버 swap 함수
void swap(Widget<T> a, Widget<T> b) // 이번엔 std 네임스페이스의 일부가 아님
{
a.swap(b);
}
}
인자 기반 탐색(argument-dependent lookup) 혹은 쾨니그 탐색(Koenig lookup)
어떤 swap이 호출될까?
template<typename T>
void doSomething(T& obj1, T& obj2)
{
…
swap(obj1, obj2);
…
}
 std에 있는 일반형 swap?
 std의 일반형을 특수화한 버전?
 T타입 전용의 버전
T 타입 전용버전이 우선 호출, 없으면 일반형
template<typename T>
void doSomething(T& obj1, T& obj2)
{
using std::swap; // std::swap을 이 함수 안으로 끌어온다.
…
swap(obj1, obj2); // T 타입 전용의 swap을 호출한다.
}
정리하면
 std::swap이 특정 타입에 대해 느리게 동작할 여지가 있다면 swap 멤버 함수를 제공하자.
 멤버 swap을 제공했으면, 이멤버를 호출하는 비멤도 swap도 제공하자.
 클래스에 대해서는, std::swap도 특수화 하자.
 사용자 입장에서 swap을 호출할 때는, std::swap에 대한 using 선언을 넣어 준 후 네임스페이스 한
정 없이 swap을 호출하자.
 사용자 정의 타입에 대한 std 템플릿을 완전 특수화하는 것은 가능하지만 std에 어떤 것이라도 새로
추가할 수는 없다.

Contenu connexe

Tendances

파이썬 프로퍼티 디스크립터 이해하기
파이썬 프로퍼티 디스크립터 이해하기파이썬 프로퍼티 디스크립터 이해하기
파이썬 프로퍼티 디스크립터 이해하기Yong Joon Moon
 
파이썬 객체 클래스 이해하기
파이썬  객체 클래스 이해하기파이썬  객체 클래스 이해하기
파이썬 객체 클래스 이해하기Yong Joon Moon
 
Javascript 객체생성패턴
Javascript 객체생성패턴Javascript 객체생성패턴
Javascript 객체생성패턴KIM HEE JAE
 
파이썬 namespace Binding 이해하기
파이썬 namespace Binding 이해하기 파이썬 namespace Binding 이해하기
파이썬 namespace Binding 이해하기 Yong Joon Moon
 
파이썬 class 및 function namespace 이해하기
파이썬 class 및 function namespace 이해하기파이썬 class 및 function namespace 이해하기
파이썬 class 및 function namespace 이해하기Yong Joon Moon
 
Java programming pdf
Java programming pdfJava programming pdf
Java programming pdfJi Hoon Lee
 
파이썬 class 및 인스턴스 생성 이해하기
파이썬 class 및 인스턴스 생성 이해하기파이썬 class 및 인스턴스 생성 이해하기
파이썬 class 및 인스턴스 생성 이해하기Yong Joon Moon
 
파이썬+객체지향+이해하기 20160131
파이썬+객체지향+이해하기 20160131파이썬+객체지향+이해하기 20160131
파이썬+객체지향+이해하기 20160131Yong Joon Moon
 
Web server page_ed10
Web server page_ed10Web server page_ed10
Web server page_ed10hungrok
 
python data model 이해하기
python data model 이해하기python data model 이해하기
python data model 이해하기Yong Joon Moon
 
파이썬 플라스크 이해하기
파이썬 플라스크 이해하기 파이썬 플라스크 이해하기
파이썬 플라스크 이해하기 Yong Joon Moon
 
파이썬 반복자 생성자 이해하기
파이썬 반복자 생성자 이해하기파이썬 반복자 생성자 이해하기
파이썬 반복자 생성자 이해하기Yong Joon Moon
 
파이썬+주요+용어+정리 20160304
파이썬+주요+용어+정리 20160304파이썬+주요+용어+정리 20160304
파이썬+주요+용어+정리 20160304Yong Joon Moon
 
파이썬 함수 이해하기
파이썬 함수 이해하기 파이썬 함수 이해하기
파이썬 함수 이해하기 Yong Joon Moon
 
파이썬 Special method 이해하기
파이썬 Special method 이해하기파이썬 Special method 이해하기
파이썬 Special method 이해하기Yong Joon Moon
 
[WELC] 22. I Need to Change a Monster Method and I Can’t Write Tests for It
[WELC] 22. I Need to Change a Monster Method and I Can’t Write Tests for It[WELC] 22. I Need to Change a Monster Method and I Can’t Write Tests for It
[WELC] 22. I Need to Change a Monster Method and I Can’t Write Tests for It종빈 오
 
파이썬 병렬프로그래밍
파이썬 병렬프로그래밍파이썬 병렬프로그래밍
파이썬 병렬프로그래밍Yong Joon Moon
 
Java 변수자료형
Java 변수자료형Java 변수자료형
Java 변수자료형Hyosang Hong
 
파이썬 iterator generator 이해하기
파이썬 iterator generator 이해하기파이썬 iterator generator 이해하기
파이썬 iterator generator 이해하기Yong Joon Moon
 

Tendances (20)

파이썬 프로퍼티 디스크립터 이해하기
파이썬 프로퍼티 디스크립터 이해하기파이썬 프로퍼티 디스크립터 이해하기
파이썬 프로퍼티 디스크립터 이해하기
 
파이썬 객체 클래스 이해하기
파이썬  객체 클래스 이해하기파이썬  객체 클래스 이해하기
파이썬 객체 클래스 이해하기
 
Javascript 객체생성패턴
Javascript 객체생성패턴Javascript 객체생성패턴
Javascript 객체생성패턴
 
파이썬 namespace Binding 이해하기
파이썬 namespace Binding 이해하기 파이썬 namespace Binding 이해하기
파이썬 namespace Binding 이해하기
 
파이썬 class 및 function namespace 이해하기
파이썬 class 및 function namespace 이해하기파이썬 class 및 function namespace 이해하기
파이썬 class 및 function namespace 이해하기
 
Java programming pdf
Java programming pdfJava programming pdf
Java programming pdf
 
파이썬 class 및 인스턴스 생성 이해하기
파이썬 class 및 인스턴스 생성 이해하기파이썬 class 및 인스턴스 생성 이해하기
파이썬 class 및 인스턴스 생성 이해하기
 
파이썬+객체지향+이해하기 20160131
파이썬+객체지향+이해하기 20160131파이썬+객체지향+이해하기 20160131
파이썬+객체지향+이해하기 20160131
 
Web server page_ed10
Web server page_ed10Web server page_ed10
Web server page_ed10
 
python data model 이해하기
python data model 이해하기python data model 이해하기
python data model 이해하기
 
파이썬 플라스크 이해하기
파이썬 플라스크 이해하기 파이썬 플라스크 이해하기
파이썬 플라스크 이해하기
 
파이썬 반복자 생성자 이해하기
파이썬 반복자 생성자 이해하기파이썬 반복자 생성자 이해하기
파이썬 반복자 생성자 이해하기
 
파이썬+주요+용어+정리 20160304
파이썬+주요+용어+정리 20160304파이썬+주요+용어+정리 20160304
파이썬+주요+용어+정리 20160304
 
파이썬 함수 이해하기
파이썬 함수 이해하기 파이썬 함수 이해하기
파이썬 함수 이해하기
 
파이썬 Special method 이해하기
파이썬 Special method 이해하기파이썬 Special method 이해하기
파이썬 Special method 이해하기
 
[WELC] 22. I Need to Change a Monster Method and I Can’t Write Tests for It
[WELC] 22. I Need to Change a Monster Method and I Can’t Write Tests for It[WELC] 22. I Need to Change a Monster Method and I Can’t Write Tests for It
[WELC] 22. I Need to Change a Monster Method and I Can’t Write Tests for It
 
파이썬 병렬프로그래밍
파이썬 병렬프로그래밍파이썬 병렬프로그래밍
파이썬 병렬프로그래밍
 
javascript03
javascript03javascript03
javascript03
 
Java 변수자료형
Java 변수자료형Java 변수자료형
Java 변수자료형
 
파이썬 iterator generator 이해하기
파이썬 iterator generator 이해하기파이썬 iterator generator 이해하기
파이썬 iterator generator 이해하기
 

En vedette

Midterm presentation revised2
Midterm presentation revised2Midterm presentation revised2
Midterm presentation revised2예인 조
 
디발자가 말하는 시선을 끄는 PPT
디발자가 말하는 시선을 끄는 PPT디발자가 말하는 시선을 끄는 PPT
디발자가 말하는 시선을 끄는 PPTJungwon An
 
Apache MINA를 사용한 네트워크 어플리케이션 개발
Apache MINA를 사용한 네트워크 어플리케이션 개발Apache MINA를 사용한 네트워크 어플리케이션 개발
Apache MINA를 사용한 네트워크 어플리케이션 개발trustinlee
 
Citation indexes(201501) ppt
Citation indexes(201501) pptCitation indexes(201501) ppt
Citation indexes(201501) pptYulee Kwon
 
개경프 컨셉기획 발표 PPT
개경프 컨셉기획 발표 PPT개경프 컨셉기획 발표 PPT
개경프 컨셉기획 발표 PPT수빈 박
 
[피키캐스트] 5학년선배 ppt 템플릿 레이아웃
[피키캐스트] 5학년선배 ppt 템플릿 레이아웃[피키캐스트] 5학년선배 ppt 템플릿 레이아웃
[피키캐스트] 5학년선배 ppt 템플릿 레이아웃o_senior
 
06월 26일 진로 3 d 프로그래밍 발표
06월 26일 진로 3 d 프로그래밍 발표06월 26일 진로 3 d 프로그래밍 발표
06월 26일 진로 3 d 프로그래밍 발표희규 김
 
2014 공유허브의 날 8. 코코팜스 양안모
2014 공유허브의 날 8. 코코팜스 양안모2014 공유허브의 날 8. 코코팜스 양안모
2014 공유허브의 날 8. 코코팜스 양안모Creative Commons Korea
 
07 엔트리와 함께하는 피지컬 컴퓨팅(센서보드)
07 엔트리와 함께하는 피지컬 컴퓨팅(센서보드)07 엔트리와 함께하는 피지컬 컴퓨팅(센서보드)
07 엔트리와 함께하는 피지컬 컴퓨팅(센서보드)entrylabs
 
피피티 최종
피피티 최종피피티 최종
피피티 최종Juheon Lee
 
문화기행팀
문화기행팀문화기행팀
문화기행팀kyobosns
 
designDIVE 2020_7팀 환경자원
designDIVE 2020_7팀 환경자원designDIVE 2020_7팀 환경자원
designDIVE 2020_7팀 환경자원designDIVE
 
INBRIEF_STARTstart with Prezi vol.01-입문편
INBRIEF_STARTstart with Prezi vol.01-입문편INBRIEF_STARTstart with Prezi vol.01-입문편
INBRIEF_STARTstart with Prezi vol.01-입문편INBRIEF COMMUNICATION
 
Electrical Fire Data Research
Electrical Fire Data ResearchElectrical Fire Data Research
Electrical Fire Data Researchjohgo1004
 
간호인력 개편(협의체)에 대한 전체 간호대 학생 설문조사 안내 PPT
간호인력 개편(협의체)에 대한 전체 간호대 학생 설문조사 안내 PPT간호인력 개편(협의체)에 대한 전체 간호대 학생 설문조사 안내 PPT
간호인력 개편(협의체)에 대한 전체 간호대 학생 설문조사 안내 PPT수경 박
 
[Design dive] eyecan발표(web)
[Design dive] eyecan발표(web)[Design dive] eyecan발표(web)
[Design dive] eyecan발표(web)준석 이
 
Micro Marketing for Second Button(by Pistachio)
Micro Marketing for Second Button(by Pistachio)Micro Marketing for Second Button(by Pistachio)
Micro Marketing for Second Button(by Pistachio)d.AntWort
 

En vedette (20)

Midterm presentation revised2
Midterm presentation revised2Midterm presentation revised2
Midterm presentation revised2
 
디발자가 말하는 시선을 끄는 PPT
디발자가 말하는 시선을 끄는 PPT디발자가 말하는 시선을 끄는 PPT
디발자가 말하는 시선을 끄는 PPT
 
Apache MINA를 사용한 네트워크 어플리케이션 개발
Apache MINA를 사용한 네트워크 어플리케이션 개발Apache MINA를 사용한 네트워크 어플리케이션 개발
Apache MINA를 사용한 네트워크 어플리케이션 개발
 
Citation indexes(201501) ppt
Citation indexes(201501) pptCitation indexes(201501) ppt
Citation indexes(201501) ppt
 
CX Design Game 한글버전
CX Design Game 한글버전CX Design Game 한글버전
CX Design Game 한글버전
 
개경프 컨셉기획 발표 PPT
개경프 컨셉기획 발표 PPT개경프 컨셉기획 발표 PPT
개경프 컨셉기획 발표 PPT
 
[피키캐스트] 5학년선배 ppt 템플릿 레이아웃
[피키캐스트] 5학년선배 ppt 템플릿 레이아웃[피키캐스트] 5학년선배 ppt 템플릿 레이아웃
[피키캐스트] 5학년선배 ppt 템플릿 레이아웃
 
Build Features, Not Apps
Build Features, Not AppsBuild Features, Not Apps
Build Features, Not Apps
 
06월 26일 진로 3 d 프로그래밍 발표
06월 26일 진로 3 d 프로그래밍 발표06월 26일 진로 3 d 프로그래밍 발표
06월 26일 진로 3 d 프로그래밍 발표
 
2014 공유허브의 날 8. 코코팜스 양안모
2014 공유허브의 날 8. 코코팜스 양안모2014 공유허브의 날 8. 코코팜스 양안모
2014 공유허브의 날 8. 코코팜스 양안모
 
07 엔트리와 함께하는 피지컬 컴퓨팅(센서보드)
07 엔트리와 함께하는 피지컬 컴퓨팅(센서보드)07 엔트리와 함께하는 피지컬 컴퓨팅(센서보드)
07 엔트리와 함께하는 피지컬 컴퓨팅(센서보드)
 
피피티 최종
피피티 최종피피티 최종
피피티 최종
 
문화기행팀
문화기행팀문화기행팀
문화기행팀
 
designDIVE 2020_7팀 환경자원
designDIVE 2020_7팀 환경자원designDIVE 2020_7팀 환경자원
designDIVE 2020_7팀 환경자원
 
INBRIEF_STARTstart with Prezi vol.01-입문편
INBRIEF_STARTstart with Prezi vol.01-입문편INBRIEF_STARTstart with Prezi vol.01-입문편
INBRIEF_STARTstart with Prezi vol.01-입문편
 
Electrical Fire Data Research
Electrical Fire Data ResearchElectrical Fire Data Research
Electrical Fire Data Research
 
간호인력 개편(협의체)에 대한 전체 간호대 학생 설문조사 안내 PPT
간호인력 개편(협의체)에 대한 전체 간호대 학생 설문조사 안내 PPT간호인력 개편(협의체)에 대한 전체 간호대 학생 설문조사 안내 PPT
간호인력 개편(협의체)에 대한 전체 간호대 학생 설문조사 안내 PPT
 
[Design dive] eyecan발표(web)
[Design dive] eyecan발표(web)[Design dive] eyecan발표(web)
[Design dive] eyecan발표(web)
 
A+ Asset Advisor
A+ Asset AdvisorA+ Asset Advisor
A+ Asset Advisor
 
Micro Marketing for Second Button(by Pistachio)
Micro Marketing for Second Button(by Pistachio)Micro Marketing for Second Button(by Pistachio)
Micro Marketing for Second Button(by Pistachio)
 

Similaire à Effective c++(chapter3,4)

Api design for c++ ch3 pattern
Api design for c++ ch3 patternApi design for c++ ch3 pattern
Api design for c++ ch3 patternjinho park
 
이펙티브 C++ 공부
이펙티브 C++ 공부이펙티브 C++ 공부
이펙티브 C++ 공부quxn6
 
Effective c++ 1~8장
Effective c++ 1~8장 Effective c++ 1~8장
Effective c++ 1~8장 Shin heemin
 
Effective c++chapter3
Effective c++chapter3Effective c++chapter3
Effective c++chapter3성연 김
 
Effective modern cpp item18, 19
Effective modern cpp item18, 19Effective modern cpp item18, 19
Effective modern cpp item18, 19진화 손
 
Effective c++(chapter 5,6)
Effective c++(chapter 5,6)Effective c++(chapter 5,6)
Effective c++(chapter 5,6)문익 장
 
Effective c++ 정리 chapter 4
Effective c++ 정리 chapter 4Effective c++ 정리 chapter 4
Effective c++ 정리 chapter 4연우 김
 
Effective C++ Chapter 3 Summary
Effective C++ Chapter 3 SummaryEffective C++ Chapter 3 Summary
Effective C++ Chapter 3 SummarySeungYeonChoi10
 
모어 이펙티브 c++ 5장 스터디
모어 이펙티브 c++ 5장 스터디모어 이펙티브 c++ 5장 스터디
모어 이펙티브 c++ 5장 스터디quxn6
 
Windows via c++ part 1
Windows via c++ part 1Windows via c++ part 1
Windows via c++ part 1Shin heemin
 
effective c++ chapter 3~4 정리
effective c++ chapter 3~4 정리effective c++ chapter 3~4 정리
effective c++ chapter 3~4 정리Injae Lee
 
More effective c++ chapter1 2_dcshin
More effective c++ chapter1 2_dcshinMore effective c++ chapter1 2_dcshin
More effective c++ chapter1 2_dcshinDong Chan Shin
 
C++ Advanced 강의 1주차
C++ Advanced 강의 1주차C++ Advanced 강의 1주차
C++ Advanced 강의 1주차HyunJoon Park
 
Effective c++ chapter3, 4 요약본
Effective c++ chapter3, 4 요약본Effective c++ chapter3, 4 요약본
Effective c++ chapter3, 4 요약본Dong Chan Shin
 
More effective c++ chapter1,2
More effective c++ chapter1,2More effective c++ chapter1,2
More effective c++ chapter1,2문익 장
 
Effective c++ Chapter1,2
Effective c++ Chapter1,2Effective c++ Chapter1,2
Effective c++ Chapter1,2문익 장
 
이펙티브 C++ 스터디
이펙티브 C++ 스터디이펙티브 C++ 스터디
이펙티브 C++ 스터디quxn6
 
Effective c++chapter4
Effective c++chapter4Effective c++chapter4
Effective c++chapter4성연 김
 
Modern C++ 프로그래머를 위한 CPP11/14 핵심
Modern C++ 프로그래머를 위한 CPP11/14 핵심Modern C++ 프로그래머를 위한 CPP11/14 핵심
Modern C++ 프로그래머를 위한 CPP11/14 핵심흥배 최
 
Refelction의 개념과 RTTR 라이브러리
Refelction의 개념과 RTTR 라이브러리Refelction의 개념과 RTTR 라이브러리
Refelction의 개념과 RTTR 라이브러리ssuser7c5a40
 

Similaire à Effective c++(chapter3,4) (20)

Api design for c++ ch3 pattern
Api design for c++ ch3 patternApi design for c++ ch3 pattern
Api design for c++ ch3 pattern
 
이펙티브 C++ 공부
이펙티브 C++ 공부이펙티브 C++ 공부
이펙티브 C++ 공부
 
Effective c++ 1~8장
Effective c++ 1~8장 Effective c++ 1~8장
Effective c++ 1~8장
 
Effective c++chapter3
Effective c++chapter3Effective c++chapter3
Effective c++chapter3
 
Effective modern cpp item18, 19
Effective modern cpp item18, 19Effective modern cpp item18, 19
Effective modern cpp item18, 19
 
Effective c++(chapter 5,6)
Effective c++(chapter 5,6)Effective c++(chapter 5,6)
Effective c++(chapter 5,6)
 
Effective c++ 정리 chapter 4
Effective c++ 정리 chapter 4Effective c++ 정리 chapter 4
Effective c++ 정리 chapter 4
 
Effective C++ Chapter 3 Summary
Effective C++ Chapter 3 SummaryEffective C++ Chapter 3 Summary
Effective C++ Chapter 3 Summary
 
모어 이펙티브 c++ 5장 스터디
모어 이펙티브 c++ 5장 스터디모어 이펙티브 c++ 5장 스터디
모어 이펙티브 c++ 5장 스터디
 
Windows via c++ part 1
Windows via c++ part 1Windows via c++ part 1
Windows via c++ part 1
 
effective c++ chapter 3~4 정리
effective c++ chapter 3~4 정리effective c++ chapter 3~4 정리
effective c++ chapter 3~4 정리
 
More effective c++ chapter1 2_dcshin
More effective c++ chapter1 2_dcshinMore effective c++ chapter1 2_dcshin
More effective c++ chapter1 2_dcshin
 
C++ Advanced 강의 1주차
C++ Advanced 강의 1주차C++ Advanced 강의 1주차
C++ Advanced 강의 1주차
 
Effective c++ chapter3, 4 요약본
Effective c++ chapter3, 4 요약본Effective c++ chapter3, 4 요약본
Effective c++ chapter3, 4 요약본
 
More effective c++ chapter1,2
More effective c++ chapter1,2More effective c++ chapter1,2
More effective c++ chapter1,2
 
Effective c++ Chapter1,2
Effective c++ Chapter1,2Effective c++ Chapter1,2
Effective c++ Chapter1,2
 
이펙티브 C++ 스터디
이펙티브 C++ 스터디이펙티브 C++ 스터디
이펙티브 C++ 스터디
 
Effective c++chapter4
Effective c++chapter4Effective c++chapter4
Effective c++chapter4
 
Modern C++ 프로그래머를 위한 CPP11/14 핵심
Modern C++ 프로그래머를 위한 CPP11/14 핵심Modern C++ 프로그래머를 위한 CPP11/14 핵심
Modern C++ 프로그래머를 위한 CPP11/14 핵심
 
Refelction의 개념과 RTTR 라이브러리
Refelction의 개념과 RTTR 라이브러리Refelction의 개념과 RTTR 라이브러리
Refelction의 개념과 RTTR 라이브러리
 

Plus de 문익 장

Mec chapter 5,6
Mec chapter 5,6Mec chapter 5,6
Mec chapter 5,6문익 장
 
Mec++ chapter3,4
Mec++ chapter3,4Mec++ chapter3,4
Mec++ chapter3,4문익 장
 
Effective c++ chapter 7,8
Effective c++ chapter 7,8Effective c++ chapter 7,8
Effective c++ chapter 7,8문익 장
 
Tcp server / client
Tcp server / clientTcp server / client
Tcp server / client문익 장
 
삼각형으로 지면 만들기
삼각형으로 지면 만들기삼각형으로 지면 만들기
삼각형으로 지면 만들기문익 장
 
소켓 주소 구조체 다루기(윈도우 네트워크 프로그래밍)
소켓 주소 구조체 다루기(윈도우 네트워크 프로그래밍)소켓 주소 구조체 다루기(윈도우 네트워크 프로그래밍)
소켓 주소 구조체 다루기(윈도우 네트워크 프로그래밍)문익 장
 
3D Graphics Transform
3D Graphics Transform3D Graphics Transform
3D Graphics Transform문익 장
 
Direct3d overview
Direct3d overviewDirect3d overview
Direct3d overview문익 장
 

Plus de 문익 장 (12)

Mec chapter 5,6
Mec chapter 5,6Mec chapter 5,6
Mec chapter 5,6
 
Mec++ chapter3,4
Mec++ chapter3,4Mec++ chapter3,4
Mec++ chapter3,4
 
Effective c++ chapter 7,8
Effective c++ chapter 7,8Effective c++ chapter 7,8
Effective c++ chapter 7,8
 
Std bind
Std bindStd bind
Std bind
 
Winsock
WinsockWinsock
Winsock
 
C++ align
C++ alignC++ align
C++ align
 
Alignment
AlignmentAlignment
Alignment
 
Tcp server / client
Tcp server / clientTcp server / client
Tcp server / client
 
삼각형으로 지면 만들기
삼각형으로 지면 만들기삼각형으로 지면 만들기
삼각형으로 지면 만들기
 
소켓 주소 구조체 다루기(윈도우 네트워크 프로그래밍)
소켓 주소 구조체 다루기(윈도우 네트워크 프로그래밍)소켓 주소 구조체 다루기(윈도우 네트워크 프로그래밍)
소켓 주소 구조체 다루기(윈도우 네트워크 프로그래밍)
 
3D Graphics Transform
3D Graphics Transform3D Graphics Transform
3D Graphics Transform
 
Direct3d overview
Direct3d overviewDirect3d overview
Direct3d overview
 

Effective c++(chapter3,4)

  • 2. resource  사용을 일단 마치고 난 후엔 시스템에 돌려주어야 하는 모든 것  가져와서 다 썻으면 해제해야, 즉 놓아 주어야 한다.  동적 할당 메모리(메모리를 할당하고서 해제하지 않으면 memory leak)
  • 3. 자원을 항상 해제되도록 하는 방법  자원을 객체에 넣고  그 자원 해제를 소멸자가 맡도록 하며,  그 소멸자가 반드시 호출되도록 만든다.
  • 4. auto_ptr  포인터와 비슷하게 동작하는 객체(smart pointer)  가리키고 있는 대상에 대해 소멸자가 자동으 로 delete를 불러주도록 설계되어 있다.  한 객체를 동시에 둘이 가리킬 수 없다. 복사생 성하거나 대입하면 한 auto_ptr은 null이 된다. std::auto_ptr<Investment>(createInvestment ());
  • 5. 자원 관리에 객체를 사용하는 방법1  자원을 획득한 후에 자원 관리 객체에 넘긴다.  자원 획득 즉 초기화(Resource Acquisition is Initialization:RAII)  자원 획득과 자원 관리 객체의 초기화가 한 문장에서 이루어 진다.
  • 6. 자원 관리에 객체를 사용하는 방법2  자원 관리 객체는 자신의 소멸자를 사용해서 자원이 확실히 해제되도록 한다.  소멸자는 어떤 객체가 소멸될 때 자동적으로 호출되므로 실행 제어가 어떤 경위로 블록을 떠나는가 에 상관없이 자원 해제가 제대로 이루어지게 된다.
  • 7. auto_ptr의 특성 std::auto_ptr<Investment>pInv1(creteInvestment()); std::auto_ptr<Investment>pInv2(pInv1); // pInv2가 가리지는 객체는 pInv1이 가리키는 객체 // pInv1은 null, auto_ptr의 특성 pInv1 = pInv2 // pInv1는 객체를 가리키고, pInv2는 null
  • 8. auto_ptr가 답인가?  복사 동작이 이루어지면 이전의 것은 null이 된다.  auto_ptr가 관리하는 객체는 두개 이상의 auto_ptr가 물고 있으면 안 된다.  이 두 가지 특성때문에 동적으로 할당되는 모든 자원에 대한 관리 객체로서 auto_ptr를 쓰는 것은 최선이 아닌 듯하다.
  • 9. 참조 카운팅 방식 스마트 포인터  reference-counting smart pointer(RCSP)  특정한 어떤 자원을 가리키는 외부 객체의 개 수를 유지하고 있다가 그 개수가 0이 되면 해 당 자원으로 삭제하는 스마트 포인터  garbage collection 방식과 유사  std::tr1::shared_ptr<Investment>pInv(crea teInvestment());
  • 10. reference-counting smart pointer의 특성 std::tr1::shared_ptr<Investment>pInv1(createInvestment()); std::tr1::shared_ptr<Investment>pInv1(pInv2); // auto_ptr과 달리 pInv1, pInv2가 // 동시에 객체를 가리킬 수 있다. pInv1 = pInv2; // 변화없음
  • 11. auto_ptr, tr1::shared_ptr의 공통 특성  소멸자 내부에서 delete 연산자를 사용한다.  delete [] 연산자가 아니다.  즉, 동적 할당한 배열에 auto_ptr, tr1::shared_ptr을 사용하면 안 된다. std::auto_ptr<std::string>aps(new std::string[10]); // error std::tr1::shared_ptr<int> spi(new int[1024]);; // error
  • 12. RAII 객체가 복사될 때 어떻게 해야하나?  복사를 금지한다. class Lock : private Uncopyable { public : … };
  • 13. RAII 객체가 복사될 때 어떻게 해야하나?  관리하고 있는 자원에 대해 참조 카운팅을 수행한다.  자원을 사용하고 있는 마지막 객체가 소멸될 때까지 그 자원을 해제하면 안 되는 경우  tr1::shared_ptr를 이용?  tr1::shared_ptr를 참조 카운트가 0이 될 때 자신이 가리키고 있던 대상을 삭제하도록 되어있기 때문 에 안 된다.  tr1:shared_ptr는 „삭제자(delete)‟ 지정을 허용한다.
  • 14. shared_ptr 삭제자 활용 class Lock { public : explicit Lock(Mutex *pm) // shared_ptr를 초기화하는데, 가리킬 포인터로 : mutexPtr(pm, unlock // Mutex 객체의 포인터를 사용하고 삭제자로 unlock 함수를 사용 { lock(mutexPtr.get()); ) private : std::tr1::shared_ptr<Mutex>mutexPtr; }
  • 15. RAII 객체가 복사될 때 어떻게 해야하나?  관리하고 있는 자원을 진짜로 복사한다.  깊은 복사(deep copy)
  • 16. RAII 객체가 복사될 때 어떻게 해야하나?  관리하고 있는 자원의 소유권을 옮긴다.
  • 17. 명시적 변환(explicit conversion)  tr1::shared_ptr 및 auto_ptr은 명시적 변환을 수행하는 get이라는 멤버 함수를 제공한다.  get 함수를 사용하면 각 타입으로 만든 스마트 포인터 객체에 들어있는 실제 포인터를 얻어낸다. std::tr1::shared_ptr<Investment> pInv(createInvestment()); int daysHeld(const Investment *pi); // int days = daysHeld(pInv); // error int days = daysHeld(pInv.get());
  • 18. 자원 접근과 명시적, 암시적 변환  안전성만 따지만 명시적 변환이 대체적으로 낫다.  하지만 사용자 편의성을 놓고 보면 암시적 변환이 괜찮다.  “맞게 쓰기에는 쉽게, 틀리게 쓰기에는 어렵게“
  • 19. new  메모리가 할당된다.  할당된 메모리에 대해 한 개 이상의 생성자가 호출된다.
  • 20. delete  기존에 할당된 메모리에 대해 한 개 이상의 소멸자가 호출된다.  그 후에 그 메모리가 해제된다.
  • 21. 객체 배열 delete st::string *stringPtr1 = new std::string; st::string *stringPtr1 = new std::string[100]; … delete stringPtr1; delete [] stringPtr2; typedef std::string AddressLines[4]; std::string *pal = new AddressLines // delete pal; delete [] pal;
  • 22. new로 생성한 객체는 스마트 포인터로… int priority(); void processWidget(std::tr1::shared_ptr<Widget> pw, int priority); // processWidget(new Widget, priority()); error! processWidget(std::tr1::shared_ptr<Widget>(new Widget), priority()); std::tr1::shared_ptr의 생성자는 explicit로 선언되어 있기 때문에 „new Widget‟표현식에 의해 만들어 진 포인터가 tr1::shared_ptr 타입의 객체로 바꾸는 암시적인 변환이 없다.
  • 23. 매개변수 호출 순서에 따른 위험성 processWidget(std::tr1::shared_ptr<Widget>(new Widget), priority()); 연산이 실행되는 순서 priority -> “new Widget” -> tr1::shared_ptr? 반드시 위의 순서대로 되지는 않는다. priority가 몇 번째로 호출될지는 모른다. 문제는 priority 호출부분에서 error가 발생하면 “new Widget”으로 만들었던 포인터가 유실될 수 있다.
  • 24. 해결책 std::tr1::shared_ptr<Widget> pw(new widget); // new로 생성한 객체를 스마트 포인터에 processWidget(pw, priority()); // prority 호출에 문제가 발생해도 포인터 유실 없음 // memory leak 방지 그래서 new로 생성한 객체를 스마트 포인터로 넣는 코드는 별도의 한 문장을 만들어야 한다.
  • 26. 제대로 쓰기 쉽게, 엉터리로 쓰기 어렵게 class Date { public : Date(int month, int day, int year); … }; Date d(30, 3, 1995); // 월, 일이 바뀜 Date d(3, 40, 1955); // 일이 이상한 값 struct Day { explicit Day(int d) : val (d) {} int val; };
  • 27. class Date { public: Date(const Month& m, const Day& d, const Year& y); … }; Date d(30, 3, 1955) // 자료형이 틀렸다. Date d(Day(30), Month(3), Year(1995)); // 자료형이 틀렸다. Date d(Month(3), Day(30), Year(1995));
  • 28. Investment * createInvestment(); std::tr1::shared_ptr<Investment>createInvestment(); 반환값이 shared_ptr이라는 것을 사용자가 알 수 있게 한다. 이 객체를 삭체하는 것을 깜빡하고 넘어가더라도 share_ptr가 알아서 해제한다.
  • 29. tr1::shared_ptr의 특성 이용1  생성 시점에 자원 해제 함수(„삭제자„)를 엮을 수 있다. std::tr1::shared_ptr<Investment>pInv(0, getRidOfInvestment); // error std::tr1::shared_ptr<Investment*>pInv(static_cast<Investment*>)(0), getRidOfInvestmentl // 0은 int, tr1::share_ptr가 요구하는 것은 Investmet* 타입의 실제 포인터이기 때문에 static_cast
  • 30. tr1::shared_ptr의 특성 이용2  교차 DLL 문제 해결  객체 생성 시에 어떤 동적 링크 라이브러리의 new를 썼는데 그 객체를 삭제할 때는 이전의 DLL과 다른 DLL에 있는 delete를 섰을 경우  tr1::shared_ptr의 기본 삭제자는 tr1::shared_ptr이 생성된 DLL과 동일한 DLL에서 delete를 사용하 도록 만들어져 있다.
  • 31. 좋은 클래스 설계  새로 정의한 타입의 객체 생성 및 소멸은 어떻게 이루어져야 하는가?  객체 초기화는 객체 대입과 어떻게 달라야 하는가?  새로운 타입으로 만든 객체가 값에 의해 전달되는 경우에 어떤 의미를 줄 것인가?  새로운 타입이 가질 수 있는 적법한 값에 대한 제약은 무엇으로 잡을 것인가?  기존의 클래스 상속 계통망에 맞출 것인가?  어떤 종류의 타입 변환을 허용할 것인가? (implicity, explicit)  어떤 연산자와 함수를 두어야 의미가 있을까?
  • 32. 좋은 클래스 설계  표준 함수들 중 어떤 것을 허용하지 말 것인가?  새로운 타입의 멤버에 대한 접근권한은 어느 쪽에 줄 것인가?  „선언되지 않은 인터페이스‟로 무엇을 둘 것인가?  새로 만드는 타입이 얼마나 일반적인가?  정말로 필요한 타입인가?
  • 33. pass_by_value? class Person { public : Person(); virtual ~ Person(); … private : std::string name; std::string address; }; class Student : public Person { public : Student(); ~Student(); … private: std::string schoolName; std::string schoolAddress; };
  • 34. pass-by-value? 비용이 너무 크다. bool validateStudent(Student s); Student plato; bool platoIsOK = validateStudent(plato);  plato로부터 매개변수 s 초기화시키기 위해 Sudent 복사 생성자 호출  s는 validateStudent가 복귀할 때 소멸  결국, 복사 생성자 1번, 소멸자 1번  Student객체가 생성될 때마다 string 객체 2개 생성  Student객체는 Person객체 파생이므로 Person 생성, string 객체 2개 생성  소멸도 생성과 마찬가지…
  • 35. reference-to-const  호출에 따르는 비용을 줄일 수 있다. bool validateStudent(const Student& s); // 새로 만들어지는 객체 같은 것이 없기 때문에 // 생성자와 소멸자가 전혀 호출되지 않는다. // const로 전달된 student 객체를 보호
  • 36. 복사손실 문제(slicing problem) class Window { public: … std::string name() const; virtual void display() const; }; class WindowWithScrollBars : public Window { public: … virtual void display() const; }; void printNameAndDisplay(Window s) { std::cout << w.name(); w.display(); } WindowWithScrollBars wwsb; printNameAndDisplay(wwsb);
  • 37. 복사손실 문제  매개변수 w 생성된다.  하지만 매개변수가 Windows 객체이므로, 이 객체를 상속받은 WindowWithScrollBars 객체의 고유 정보들은 손실된다.  결국, 호출하는 display()함수도 Windows 객체의 것이다.
  • 38. 복사손실 문제 해결 void printNameAndDisplay(const Windows& w) { std::coutn << w.name(); w.display(); } w를 참조자로 전달하면 w는 어떤 종류의 윈도우가 넘겨지더라고 그 윈도우의 성질을 갖게 된다.
  • 39. 함수에서 객체 반환할때 참조자 반환하지말자 class Rational { public : Rational(int numerator = 0, int denominator = 1); … private : int n, d; friend const Rational operator*(const Rational& lhs, const Rational rhs); };
  • 40. Rational a(1, 2); Rational b(3, 5); Rational c = a * b; // 객체가 생성되지 않았는데 참조자를 반환하고 있다.
  • 41. 스택을 이용한 객체 반환 cosnt Rational& operation*(const Rational& lhs, const Rational& rhs) { Rational result(lhs.n * rhs.n, lhs.d * rhs.d); // 생성자를 호출 retrun result; // result는 지역객체으로 함수가 끝날 때 소멸됨에도 불구하고 참조자를 반환 }
  • 42. 힙을 이용한 객체 반환 const Rational& operator*(const Rational& lhs, const Rational& rhs) { Rational *result = new Rational(lhs.n * rhs.n, lhs.d * rhs.d); // 생성자 호출, delete 부담 return *result; }
  • 43. static을 이용한 객체 반환 const Rational& operator*(const Rational& lhs, const Rational& rhs) { static Rational result; // 반환할 참조자가 가리킬 정적객체 result = …; return result; } 정적객체는 공유하는 값이므로 활용에 제한이 있을 뿐더러, 스레디 안전성 문제도 있다.
  • 44. 객체를 반환하는 올바른 방법 inline const Rational operator*(const Rational& 1hs, const Rational& rhs) { return Rational(lhs.n * rhs.n, lhs,d * rsh.d); } 새로운 객체를 반환하게 만드는 것이 정도이다.
  • 45. 데이터 멤버가 선언될 곳은 private  private으로 선언하면 데이터 멤버에 접근하기 위해서 멤버 함수를 써야 한다.  어떤 데이터 멤버는 public이고, 어떤 데이터 멤버는 private이라면 일관성이 사라진다.  함수를 통해서만 데이터 멤버에 접근할 수 있도록 구현해 두면, 데이터 멤버를 나중에 계산식으로 대체할 수 있을 것이다.(캡슐화, encapsulation)  public 데이터 멤버가 있고, 이것을 제거한다고 가정해보자. 캡슐화가 얼마나 중요한지 알 수 있다.  protected도 마찬가지로 안전하지 않다.  결국은 캡슐화를 고려하였을 때, 데이터 멤버는 private에 선언하는 것이 답이다.
  • 46. 멤버함수보다는 비멤버 비프렌드 함수 class WebBrowser { public: … void clearCache(); void clearHistory(); void removeCookies(); } class WebBrowser { public: … void clearEverything(); // clearCache, // clearHistory, // removeCookies … };
  • 47. 비멤버 버전 void clearBrowser (WebBrowser& wb) { wb.clearCache(); wb.clearHistory(); wb.removeCookies(); } 멤버 버전이 좋을까? 비멤버 버전이 좋을까?
  • 48. 비멤버 버전의 장점  캡슐화  피키징 유연성(packaging flexibility)가 높아진다.  컴파일 의존도도 낮춘다.  확장성이 높아진다.  결국, 비멤버 방법이 멤버 함수보다 여러모로 낫다.
  • 49. namespace를 활용한 비멤버 함수 namespace WebBrowserStuff { class WebBrowser {…}; void clearBrowser {WebBrowser& wb}; … }
  • 50. namesapce를 활용한 비멤버 함수의 장점  namespace는 class와 달리 여러 개의 소스 파일에 나뉘어 흩어질 수 있다.  다시 말해, 필요할 때 기능을 불러다 쓰면 된다. WebBrowser객체가 없어도 쓸 수 있다.  응용도가 높은 편의 함수들과 응용도가 낮은 편의 함수를 구분하여 관리하면 컴파일 의존성에서 비 교적 자유로울 수 있다.  클래스 멤버 함수로 사용하게 되면 기능을 쪼개는 것이 불가능하다.  편의 함수 전체를 여러 개의 헤더 파일에(그러나 하나의 namespace) 나누어 놓으면 편의 함수 집 합의 확장도 쉬워진다. 해당 네임스페이스에 비멤버 비프렌드 함수를 추가하면 끝.
  • 51. 타입변환이 모든 매개변수에 적용된다면 비멤버 함수로 // 유리수를 나타내는 클래스 class Rational { public: Rational(int numerator = 0, int denominator = 1); int numerator() const; int denominator() const; const Rational operator*(const Rational& rhs) const; private: … };
  • 52. Rational oneEighth(1, 8); Rational oneHalf(1, 2); Rational result = oneHalf * oneEighth; // OK result = result * oneEighth; // OK result = oneHalf * 2; // OK result = 2 * oneHalf; // error result = oneHalf.operator*(2); // OK result = 2.operator*(oneHalf); // error 암시적 타입 변환에 대해 매개변수가 먹혀들려면 매개변수 리스트에 들어있어야 한다.
  • 53. 암시적 변환을 가능하게 하기위해서 class Rational { … }; const Rational operator*(const Rational& lhs, const Rational& rhs) // 비멤버 함수로 만들었다. { // 모든 인자에 대해 암시적 타입 변환 return Raional(lhs.numerator() * rhs.numerator(), lhs.denominator() * rhs.denominator()); } Rational oneFourth(1, 4); Rational result; result = oneFourth * 2; result = 2 * oneFourth;
  • 54. 예외를 던지지 않는 swap // 표준 라이브러리에서 제공하는 swap namespce std { template<typename T> void swap(T& a, T& b) { T temp(a); a = b; b = temp; } }
  • 55. pimpl 관용구 class Widget Impl { public : … private : int a, b, c; std::vector<double> V; … }; class Widget { public : Widget (const Widget& rhs); Widget& operator = (const Widget& rhs) { … *pImpl = *(rhs.pImpl); … } … private : WidgetImpl *pImpl; };
  • 56. 표준 swap 알고리즘의 빈틈  위의 Widget 객체를 직접 맞바꾼다면? pImpl포인터만 바꾸는 것이 아니다.  Widget 객체 세 개를 복사하고, WidgetImpl 객체 세 개도 복사한다.  비효율적이다.
  • 57. std::swap 특수화 namespace std { template<> // 완전 템플릿 특수화를 컴파일러에게 알려 준다. void swap<Widget>(Widget& a, Widget& b) { swap(a.pImpl, b.pImpl); } }
  • 58. class Widget { public : … void swap(Widget& other) { using std::swap; swap(pImpl, other.pImpl); } … }; namespace std { template<> void swap<Widget>(Widget& a, Widget& b) { a.swap(b); } }
  • 59. 함수는 부분 특수화가 되지 않는다. // Widget이 클래스가 아닌 클래스 템플릿 template<typename T> class WidgetImpl {…}; template<typename T> class Widget {…}; namespace std { template<typename T> void swap<Widget<T>>(Widget<T>& a, Widget<T>& b) { a.swap(b); } } 위 코드는 적법하지 않다. C++은 클래스 템플릿의 부분 특수화는 인정 함수 템플릿에 대해서는 허용하지 않는다.
  • 60. 함수 템플릿의 부분적 특수화는 오버로드 namespace std { template<typename T> void swap(Widget<T>& a, Widget<T>& b) { a.swap(b) }; } 위의 코드는 유효하지 않다.  std 내의 템플릿에 대한 완전 특수화는 OK  std에 새로운 템플릿을 추가하는 것은 OK 아 님
  • 61. 템플릿 전용 버전으로 만들자 namespace WidgetStuff { … template<typename T> class Widget {…}; … template<typename T> // 비멤버 swap 함수 void swap(Widget<T> a, Widget<T> b) // 이번엔 std 네임스페이스의 일부가 아님 { a.swap(b); } } 인자 기반 탐색(argument-dependent lookup) 혹은 쾨니그 탐색(Koenig lookup)
  • 62. 어떤 swap이 호출될까? template<typename T> void doSomething(T& obj1, T& obj2) { … swap(obj1, obj2); … }  std에 있는 일반형 swap?  std의 일반형을 특수화한 버전?  T타입 전용의 버전
  • 63. T 타입 전용버전이 우선 호출, 없으면 일반형 template<typename T> void doSomething(T& obj1, T& obj2) { using std::swap; // std::swap을 이 함수 안으로 끌어온다. … swap(obj1, obj2); // T 타입 전용의 swap을 호출한다. }
  • 64. 정리하면  std::swap이 특정 타입에 대해 느리게 동작할 여지가 있다면 swap 멤버 함수를 제공하자.  멤버 swap을 제공했으면, 이멤버를 호출하는 비멤도 swap도 제공하자.  클래스에 대해서는, std::swap도 특수화 하자.  사용자 입장에서 swap을 호출할 때는, std::swap에 대한 using 선언을 넣어 준 후 네임스페이스 한 정 없이 swap을 호출하자.  사용자 정의 타입에 대한 std 템플릿을 완전 특수화하는 것은 가능하지만 std에 어떤 것이라도 새로 추가할 수는 없다.