U E D R , A S I H C RSS

AcceleratedC++/Chapter14

1. Chapter 14 Managing memory (almost) automatically

Student_info ด๋ž˜Šค๋Š” ๋ ˆฝ”๋“œ˜ „Ž˜Šค. ๋ ˆฝ”๋“œ˜ ๋ฉ”๋ชจ๋ฆฌ ณต„„ ด€๋ฆฌ•œ‹ค.
ด๋ ‡ฒŒ 2ฐ€ง€˜ ถ”ƒ ธฐ๋Šฅ„ กฐ••„œ ๋งŒ๋“คฒŒ ๋˜๋Š” ฒƒ€ —ˆˆ •œ ด๋ž˜Šค „„•Œ๋ฌธฒฝšฐฐ€ ๋งŽ๋‹ค.

žฅ—„œ๋Š” ฌ„˜๋Ÿผ ๋™ž‘•˜ง€๋งŒ, žฒด ๋ฉ”๋ชจ๋ฆฌ ด€๋ฆฌ๋ฅผ ฌ••˜๋Š” ด๋ž˜Šค๋ฅผ ž‘„•˜   •ฉ๋‹ˆ๋‹ค.
๋‚ด๋ถ€˜ •œ œฒด๋ฅผ ฐ€๋ฆฌ‚ค๋Š” ฌ„™€ ๋น„Š•œ ฒด๋ฅผ   ˆžˆ ‚ฌšฉ•˜๋ฉด ๋ถˆ•„š”•œ ๋ณต‚ฌฐ€ –‰•ง€๋Š” „ฑ๋Šฅƒ˜ ๋ฌธ œ๋ฅผ •ฒฐ•  ˆ˜ žˆ๋‹ค.

๋งŒ•ฒด xฐ€ y๋ฅผ ฐ€๋ฆฌ‚จ๋‹ค๋ฉด x๋ฅผ ๋ณต‚ฌ•œ‹  •„œ y๋„ ๋ณผ‚ฌ๋ นŒ?
๋งŒ•ฝ yฐ€ x˜ ๋ฉค๋ฒ„ผ๋ฉด ด๋Š” ˜ณ๋‹ค. ธ๋ ‡ง€๋งŒ –ดฉŒ๋‹ฐ€ y๋ฅผ ฐ€๋ฆฌ‚คฒŒ ๋œ ฒฝšฐ๋ผ๋ฉด ด๋Š” ˜ง€ •Š๋‹ค.

žฅ˜ ๋‚ดšฉ€ ƒ๋‹žˆ ถ”ƒ ธฐ ๋•Œ๋ฌธ— ƒ๋‹žˆ ฃผ˜ นŠ€ •ฐ€ •„š”•˜‹ค.

1.1. 14.1 Handles that copy their objects

13žฅ—„œ ๋ฌธ œ๋ฅผ •ฒฐ•˜ธฐœ„•„œ๋Š” „œ๋กœ‹ค๋ฅธ ƒ€ž…˜ ฒด๋ฅผ •œœ˜ ปฌ๋ ‰…˜—  –•˜๋Š” ๋ฐฉ๋ฒ••„š”–ˆ๋‹ค.
13.3.1 ˆ˜ ฒซ๋ฒˆงธ •ฒฐ๋ฒ•—„ ๋А ด๋ฅผ œ„•„œ ฌ„ฐ๋ฅผ ‚ฌšฉ•˜—ฌ„œ Core ˜€ Core๋กœ ๋ถ€„ŒŒƒ๋œ ฒด๋“ค„ ƒ„•˜—ฌ ปฌ๋ ‰…˜ ๋‚ด๋ถ€˜ ฌ„ฐ๋“ค๋กœ ฐ€๋ฆฌ‚ค๋„๋ก •˜˜€๋‹ค. ๋”ฐ๋„œ ฒฝšฐ ‚ฌšฉž ฝ”๋“œ๋Š” ฒด˜ ๋™ ƒ„ฑ, • œ— ด€๋ จ๋œ ฒƒ๋“ค„ ˜๋ฆฌ•  ฑ…ž„žˆ—ˆ๋‹ค.

 €ˆ˜ค€ ž๋ฃŒตฌกฐฌ„ฐ๋ฅผ ง ‘ƒš”•œผ๋กœ„œ ƒธฐ๋Š” ๋ฌธ œ 
* ฌ„ฐ๋ฅผ ๋ณต‚ฌ•˜๋Š” ฒƒ€ ธ ๋Œ€ƒ ฒด๋ฅผ ๋ณต‚ฌ•˜๋Š” ฒƒณผ๋Š” ๋‹ค๋ฆ„.
* ฌ„˜ †Œ๋ฉธฒด˜ †Œ๋ฉธ„ ˜๋ฏธ•˜ง€ •Š๋Š”๋‹ค. (memory leak)
* ฌ„†Œ๋ฉธ‹œ‚คง€ •Š , ฒด๋ฅผ †Œ๋ฉธ• ฒฝšฐ dangling pointer ๋ฐœƒ.
* ฌ„ƒ„‹œ ดˆธฐ™”•˜ง€ •Šœผ๋ฉด, ฌ„ฐ๋ฅผ ๋ฐ”ธ๋”ฉ๋˜ง€ •Š€ ƒƒœฐ€๋œ‹ค.
๋งˆง€๋ง‰ 2ฐ€ง€˜ ฒฝšฐ๋Š” ฌ„ฐ๋ฅผ ๋‹ค๋ฅธ ณณ—„œ ฐธกฐ•  ฒฝšฐ –ด๋–ค –ด๋‚ ง€ •Œ ˆ˜ —†๋‹ค.

13.5˜ Student_info ๋Š” ”„๋กœธ๋ž˜๋จธฐ€ ๋‚ด๋ถ€˜ Coreฒด๋ฅผ ๋ณผ ˆ˜—† , ž๋™œผ๋กœ ๋ฉ”๋ชจ๋ฆฌ ด€๋ฆฌฐ€ ๋˜๋„๋ก€ –ˆœผ๋‚˜, ๋ฉ”†Œ๋“œ๋“คด Coreด๋ž˜Šค˜ public—ฐ‚ฐ๋“ค„ ธ๋Œ€๋กœ ๋”ฐ๋ฅด๋Š” ฒƒ๋“คด ๋งŽ๋‹ค.
žฅ—„œ๋Š” ด๋Ÿฐ •ธ๋“ค(handle)ด๋ž˜Šค๋ฅผ ผ๋ฐ˜ ธ ๋ฐฉ‹œผ๋กœ ด€๋ฆฌ•˜๋Š” ฒƒ„ •ŒฒŒ ๋œ‹ค.

1.1.1. 14.1.1  œ„ค๋ฆญ •ธ๋“ค ด๋ž˜Šค(generic handle class)

ด๋ž˜Šค๋Š” ฒด˜ ˜•— ๋ฌดด€•œฒŒ ๋™ž‘•˜—ฌ••˜๋ฏ€๋กœ …œ”Œ๋ฆฟœผ๋กœ ž‘„•œ‹ค.
Handle ด๋ž˜Šค˜ š”ตฌ‚ฌ•
* Handle€ ฒด˜ ฐธกฐฐ’
* Handle€ ๋ณต‚ฌฐ€ ฐ€๋Šฅ•˜‹
* Handle ฒดฐ€ ๋‹ค๋ฅธ ฒด— ๋ฐ”ธ๋”ฉ๋˜–ด žˆ๋Š”ง€ ™•ฐ€๋Šฅ
* Handleด๋ž˜Šคฐ€ ฐ€๋ฆฌ‚ค๋Š” ฒดฐ€ ƒ†ตฌกฐ˜ ด๋ž˜Šค˜•„ ฐ€๋ฆฌ‚จ๋‹ค๋ฉด virtual — ˜•ง€ •๋œ —ฐ‚ฐ—๋Œ€•„œ‹˜•„„  œณต•œ‹ค.

‚ฌšฉžฐ€ Handle ด๋ž˜Šค๋ฅผ šฉ•„œ Šน ••œ œฒด— Handle„ ๋ถ™ฒŒ ๋˜๋ฉด Handle€ ฒด˜ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ด€๋ฆฌ•˜ฒŒ ๋œ‹ค.
๋Œ€‹  ผ๋‹ฒด๋Š” ˜ง •˜๋‚˜˜ Handle๋งŒ„ ๋ถ€ฐฉ‹œœ••˜๋ฉฐ, ผ๋‹จ ๋ถ€ฐฉ‹œ‚จ ๋’ค—๋Š” ฌ„ฐ€•„‹Œ Handle„ š”•„œ ฒด—  ‘•••œ‹ค.
ฆ‰ Handle†Œ๋ฉธ๋˜๋ฉด Handleฐ€๋ฆฌ‚ค๋Š” ฒด๋„ †Œ๋ฉธ๋˜ฒŒ ๋œ‹ค. ‚ฌšฉž๋Š” ๋ฐ”ธ๋”ฉ•ˆ๋œ ฒด๋ฅผ ฐ€๋ฆฌ‚ค๋Š” •ธ๋“ค„ ๋งŒ๋“คˆ˜๋Š” žˆง€๋งŒ ฒฝšฐ •ธ๋“ค—  ‘•˜ฒŒ๋˜๋ฉด ˜ˆ™ธ ƒ™ฉ„ ๋ฐœƒ•˜ฒŒ๋œ‹ค. (•„‹ˆ๋ฉด ˜Œ ƒ„‹œ ฒดฐ€ ๋ฐ”ธ๋”ฉ ๋˜–ดžˆ๋Š”ง€๋ฅผ ฒ€‚ฌ•˜๋„๋ก •˜๋ฉด ๋œ‹ค.)
~cpp 
template <class T> class Handle {
public:
	Handle(): p(0) { }	// ธฐ๋ณธƒ„ž๋Š” ๋‚ด๋ถ€ ๋ฉค๋ฒ„๋ฅผ 0œผ๋กœ ดˆธฐ™”•˜—ฌ„œ •„ง ๋ฐ”ธ๋”ฉ•ˆ๋œ ƒƒœž„„ ๋‚˜ƒ€๋‚ธ๋‹ค.
	Handle(const Handle& s) : p(0) { if (s.p) p = s.p->clone(); }	// ๋ณต‚ฌ ƒ„ž๋Š” ž๋กœ ๋ฐ›€ ฒด˜ clone() •ˆ˜๋ฅผ †ต•„œ ƒˆ๋กœšด ฒด๋ฅผ ƒ„•˜  ฒƒ„ ๋Œ€ž…•œ‹ค.
	Handle& operator=(const Handle&);
	~Handle() { delete p; }

	Handle(T* t):p(t) { }

	operator bool() const { return p; }
	T& operator*() const;
	T* operator->() const;

private:
	T* p;
};

template<class T> Handle<T>& Handle<T>::operator=(const Handle& rhs) {
	if(&rhs != this) {		// žธฐ ฐธกฐ๋ฅผ กฐ‚ฌ•œ๋’ค –‰๋™๋ฐฉ‹„ ฒฐ ••œ‹ค.
		delete p;
		p = rhs.p ? rhs.p->clone() : 0;
	}
	return *this;
}
 
~cpp 
 Handle<Core> p(new Grad);	// Handle<Core> ==  Core*
				// Handle<Core> ๋Š” ƒˆ๋กœ ƒ„ฑ๋œ Grad๋ฅผ ฐ€๋ฆฌ‚จ๋‹ค.
 

~cpp 
template<class T> T& Handle<T>::operator*() const {
	if(p)
		return *p;
	throw runtime_error("unbound Handle");
}	// œธฐ™”๋ฅผ • •Œ ƒ„•œ ฒด๋ฅผ ฐ€๋ฆฌ‚ค๋Š” ฒฐณผ๋ฅผ ๋ฆฌ„•œ‹ค.

template<class T> T* Handle<T>::operator->() const {
	if(p)
		return p;
	throw runtime_error("unbound Handle");
}
 
-> —ฐ‚ฐž๋Š” ฒฌ •—ฐ‚ฐž ˜๋Ÿผ ๋ณดง€๋งŒ ๋™ž‘•˜๋Š” ๋ฐฉ‹ด ๋‹ค๋ฅธ —ฐ‚ฐž๋“คณผ๋Š” ๋‹ค๋ฅด๋‹ค. ->๋ฅผ ˜œ•˜ฒŒ ๋˜๋ฉด —ฐ‚ฐž˜ ขŒธกš”†Œ—„œ ฌ„ฐ๋ฅผ ๋Œ€‹ •„œ ‚ฌšฉฐ€๋Šฅ•œ š”†Œฐ€ ๋ฆฌ„ด๋œ‹ค.

~cpp 
// ๋™•œ ‘œ˜„
x->y;
(x.operator->())->y;

//as upper
student->y;
(student.operator->())->y;
student.p->y;
 
ƒธฐ˜  •˜—„œ *, -> —ฐ‚ฐž๋ฅผ ฐธกฐ˜•, ฌ„˜•œผ๋กœ ๋ฆฌ„•˜ฒŒ •œผ๋กœจ ž๋™œผ๋กœ ŒŒƒฒด— ๋Œ€•œ ๋™ ๋ฐ”ธ๋”ฉฐ€๋Šฅ•„‹ค.

1.1.2. 14.1.2  œ„ค๋ฆญ •ธ๋“ค ‚ฌšฉ•˜ธฐ


~cpp 
//main.cpp
#include <algorithm>
#include <ios>
#include <iomanip>
#include <iostream>
#include <stdexcept>
#include <vector>

#include "Handle.h"
#include "Student_info.h"

using std::cin;
using std::cout;
using std::domain_error;
using std::endl;
using std::sort;
using std::streamsize;
using std::setprecision;
using std::setw;
using std::string;
using std::vector;

using std::max;

bool compare_Core_handles(const Handle<Core>& lhs, const Handle<Core>& rhs) {
	return compare(*lhs, *rhs);
}

int main()
{
	vector< Handle<Core> > students;       // changed type
	Handle<Core> record;                   // changed type
	char ch;
	string::size_type maxlen = 0;

	// read and store the data
	while (cin >> ch) {
		if (ch == 'U')
			record = new Core;      // allocate a `Core' object
		else
			record = new Grad;      // allocate a `Grad' object

		record->read(cin);  //  `Handle<T>::->', then `virtual' call to `read'
		maxlen = max(maxlen, record->name().size()); // `Handle<T>::->'
		students.push_back(record);
	}

	// `compare' must be rewritten to work on `const Handle<Core>&'
	sort(students.begin(), students.end(), compare_Core_handles);

	// write the names and grades
	for (vector< Handle<Core> >::size_type i = 0;
	     i != students.size(); ++i) {
		// `students[i]' is a `Handle', which we dereference to call the functions
		cout << students[i]->name()
		     << string(maxlen + 1 - students[i]->name().size(), ' ');
		try {
			double final_grade = students[i]->grade();
			streamsize prec = cout.precision();
			cout << setprecision(3) << final_grade
			     << setprecision(prec) << endl;
		} catch (domain_error e) {
			cout << e.what() << endl;
		}
		// no `delete' statement
	}
	return 0;
}
 
Handle ด๋ž˜Šค๋Š” —ฐฒฐ๋œ ฒด˜ clone() ๋ฉค๋ฒ„•ˆ˜๋ฅผ šฉ•œ‹ค. ๋”ฐ๋„œ Coreด๋ž˜Šค— clone()๋ฉ”†Œ๋“œ๋ฅผ publicœผ๋กœ ž‘„•˜๋Š” ฒƒ•„š”•˜‹ค.

Handle<>„ šฉ•œ Student_info ˜ ตฌ˜„
~cpp 
//Student_info.h
#ifndef GUARD_Student_info
#define GUARD_Student_info

#include <iostream>
#include <string>

#include "Core.h"
#include "Handle.h"

class Student_info {
public:
	Student_info() { }
	Student_info(std::istream& is) { read(is); }
	// no copy, assign, or destructor: they're no longer needed

	std::istream& read(std::istream&);

	std::string name() const {
		if (cp) return cp->name();
		else throw std::runtime_error("uninitialized Student");
	}

	double grade() const {
		if (cp) return cp->grade();
		else throw std::runtime_error("uninitialized Student");
	}
	static bool compare(const Student_info& s1,
	                    const Student_info& s2) {
		return s1.name() < s2.name();
	}
private:
	Handle<Core> cp;	// Handle ด๋ž˜Šคฐ€ ƒ„ณผ †Œ๋ฉธ„ ž๋™™”•˜ธฐ ๋•Œ๋ฌธ— ๋ณต‚ฌ ƒ„ž, ๋Œ€ž… —ฐ‚ฐž, †Œ๋ฉธžฐ€ •„š” —†๋‹ค.
};
#endif
 

Student_info::read ˜ žฌ •˜
~cpp 
//Student_info.cpp
#include <iostream>

#include "Student_info.h"
#include "Core.h"

using std::istream;

istream& Student_info::read(istream& is)
{
	char ch;
	is >> ch;     // get record type

	// allocate new object of the appropriate type
	// use `Handle<T>(T*)' to build a `Handle<Core>' from the pointer to that object
	// call `Handle<T>::operator=' to assign the `Handle<Core>' to the left-hand side
	if (ch == 'U')
		cp = new Core(is);
	else
		cp = new Grad(is);

	return is;
}
 
ž๋™œผ๋กœ ฒด˜ ๋ฉ”๋ชจ๋ฆฌ ด€๋ฆฌฐ€ ๋˜ธฐ ๋•Œ๋ฌธ— delete ตฌ๋ฌธ„  œฑฐ•จ. Handle::operator=()— ๋‚ด๋ถ€ ๋ฉ”๋ชจ๋ฆฌ˜ • œ ตฌ๋ฌธด ๋“ค–ดžˆธฐ ๋•Œ๋ฌธ— ๋ถˆ•„š”.

1.2. 14.2 Reference-counted handles

–ด๋–ค ฒฝšฐ— ”„๋กœธ๋ž˜๋จธ๋Š” Handleด ๋Œ€ƒ ฒด๋ฅผ ๋ณต‚ฌ•˜๋Š” ˜•ƒœฐ€ •„‹ˆ๋ผ ๋‹ง€ ฐ€๋ฆฌ‚ค๋Š” ˜•ƒœ๋กœ๋งŒ ‚ฌšฉ๋˜ธฐ๋ฅผ ๋ฐ”๋ž„ ˆ˜ žˆ๋‹ค. ฆ‰ ๋™•œ ฒด๋ฅผ 2œ˜‹ค๋ฅธ Handle ฐ€๋ฆฌ‚ฌ ˆ˜ žˆ๋‹ค๋Š” ๋งด๋‹ค.
ฒฝšฐ ๋Œ€ƒฒด˜ • œ๋Š” ฒด๋ฅผ ฐ€๋ฆฌ‚ค๋Š” ๋งˆง€๋ง‰ •ธ๋“ค†Œ๋ฉธ๋ •Œ –‰• ••œ‹ค. ด๋ฅผ œ„• ˆผ๋ŸฐŠค นดšดŠธ(reference count, ฐธกฐ„ˆ˜)๋ฅผ ‚ฌšฉ•œ‹ค.
ด๋ฅผ œ„•„œ šฐ๋ฆฌ๋Š”  „˜ ด๋ž˜Šค— นดšด„ฐ(counter, „ˆ˜ธฐ)๋ฅผ ถ”ฐ€•˜  ฒด˜ ƒ„ฑ, ๋ณต‚ฌ, †Œ๋ฉธ‹œ นดšด„ฐ๋ฅผ   ˆ•˜ฒŒ ฐฑ‹ •œ‹ค.
~cpp 
//Ref_handle.h
#ifndef Ref_handle_h
#define Ref_handle_h

#include <cstddef>
#include <stdexcept>

template <class T> class Ref_handle {
public:
	// manage reference count as well as pointer
	Ref_handle(): p(0), refptr(new size_t(1)) { }
	Ref_handle(T* t):  p(t), refptr(new size_t(1)) { }
	Ref_handle(const Ref_handle& h): p(h.p), refptr(h.refptr) {
		++*refptr;
	}	// ฐธกฐ˜•œผ๋กœ ๋™ž‘•˜๋Š” Handleฒฝšฐ. นดšด„˜ ฃผ†Œ๋ฅผ ๋Œ€ƒฒด˜ นดšด„˜ ฃผ†Œ๋กœ ดˆธฐ™”, นดšด„ฐ๋ฅผ ฐ€‹œ‚จ๋‹ค.

	Ref_handle& operator=(const Ref_handle&);
	~Ref_handle();

	// as before
	operator bool() const { return p; }
	T& operator*() const {
		if (p)
			return *p;
		throw std::runtime_error("unbound Ref_handle");
	}
	T* operator->() const {
		if (p)
			return p;
		throw std::runtime_error("unbound Ref_handle");
	}

private:
	T* p;
	std::size_t* refptr;      // added
};

template <class T>
Ref_handle<T>& Ref_handle<T>::operator=(const Ref_handle& rhs)
{	// Ref_handle&๋ฅผ ž๋กœฐ–๋Š” ƒ„ž™€ ๋งˆฐฌฐ€ง€๋กœ operator= ๋„ ž๋กœ ๋ฐ›€ ๋Œ€ƒด Ref_handle ฒฝšฐ นดšด„ฐ๋ฅผ •˜๋‚˜ ฐ€‹œ‚จ๋‹ค.
	++*rhs.refptr;

	// free the left-hand side, destroying pointers if appropriate
	// —ฌธฐ„œ ๋งŒ•žธฐ ž‹ „ ๋Œ€ž…•  ฒฝšฐ—๋Š” ฒด˜ ฐธกฐ˜ นดšด„ฐ€ ๋ณ€™”•˜ง€ •ŠฒŒ๋œ‹ค.
	if (--*refptr == 0) {
		delete refptr;
		delete p;
	}	// ๋งˆง€๋ง‰ ๋Œ€ƒฒด˜ •ธ๋“คด๋ผ๋ฉด ˜„žฌ กดžฌ•˜๋Š” ๋Œ€ƒ ฒด๋ฅผ ‚ญ œ

	// copy in values from the right-hand side
	refptr = rhs.refptr;
	p = rhs.p;
	return *this;
}

template <class T> Ref_handle<T>::~Ref_handle()
{
	if (--*refptr == 0) {
		delete refptr;
		delete p;
	}
}	// †Œ๋ฉธ๋˜๋Š” •ธ๋“คด ๋Œ€ƒฒด๋ฅผ ฐ€๋ฆฌ‚ค๋Š” ๋งˆง€๋ง‰ ฒด๋ผ๋ฉด ๋ฉ”๋ชจ๋ฆฌ—„œ • œ
	// refptr๋„ ๋™ • ‹น๋œ ฒดด๋ฏ€๋กœ ๋ฉ”๋ชจ๋ฆฌ—„œ • œ•ฃผ๋Š” ฝ”๋“œฐ€ •„š”•˜‹ค.

#endif

๋ฌธ œ 
~cpp 
//Ref_handle„ ธฐ๋ฐ˜œผ๋กœ ž‘„ฑ๋œ Student_info ด๋ž˜Šค˜ ‚ฌšฉ‹œ
Student_info s1(cin);
Student_info s2 = s1;	// s1˜ ฐ’„ s2๋กœ ๋ณต‚ฌ•œ‹ค. •˜ง€๋งŒ ๋‚ด๋ถ€˜ ฒด๋Š” ฐ™€ ฒด๋ฅผ ฐ€๋ฆฌ‚จ๋‹ค.
•„š”—†๋Š” ๋ณต‚ฌ๋Š” –ด๋‚˜ง€ •Šง€๋งŒ ฒฝšฐ ”„๋กœธ๋ž˜๋จธฐ€ ›˜ •Š„ ฒฝšฐ—๋„ ๋™•œ ฒด๋ฅผ ฐ€๋ฆฌ‚ค๋Š” ด ๋ฐœƒ•œ‹ค.

1.3. 14.3 Handles that let you decide when to share data

~cpp 
//ptr.h
#ifndef GUARD_Ptr_h
#define GUARD_Ptr_h

#include <cstddef>
#include <stdexcept>

template <class T> class Ptr {
public:
	// new member to copy the object conditionally when needed
	void make_unique() {
		if (*refptr != 1) {
			--*refptr;
			refptr = new size_t(1);
			p = p? clone(p): 0;
		}
	}
	/*
	•ˆ˜๋Š” ”„๋กœธ๋ž˜๋จธฐ€ •„𔕠•Œ ˜„žฌ ฐ€๋ฆฌ‚ค๋Š” ๋‚ด๋ถ€ฒด™€ 
	๋™•œ ๋‚ดšฉ˜ ฒด๋ฅผ ๋ณต‚ฌ•œ ฒด๋ฅผ ๋งŒ๋“ค–ดค€๋‹ค.

	๋Œ€‹ — ฐ€๋ฆฌ‚ค๋Š” ๋Œ€ƒ˜ •ธ๋“คด 1œฒฝšฐ—๋Š” ด๋Ÿฐ ๋ณต‚ฌ๋ฅผ –‰•˜ง€ •Š๋Š”๋‹ค.
	*/
	// the rest of the class looks like `Ref_handle' except for its name
	Ptr(): p(0), refptr(new size_t(1)) { }
	Ptr(T* t): p(t), refptr(new size_t(1)) { }
	Ptr(const Ptr& h): p(h.p), refptr(h.refptr) { ++*refptr; }

	Ptr& operator=(const Ptr&);    // implemented analogously to 14.2/261
	~Ptr();                        // implemented analogously to 14.2/262
	operator bool() const { return p; }
	T& operator*() const;          // implemented analogously to 14.2/261
	T* operator->() const;         // implemented analogously to 14.2/261

private:
	T* p;
	std::size_t* refptr;
};

template <class T> T* clone(const T* tp)
{
	return tp->clone();
}

template<class T>
T& Ptr<T>::operator*() const { if (p) return *p; throw std::runtime_error("unbound Ptr"); }

template<class T>
T* Ptr<T>::operator->() const { if (p) return p; throw std::runtime_error("unbound Ptr"); }

template<class T>
Ptr<T>& Ptr<T>::operator=(const Ptr& rhs)
{
        ++*rhs.refptr;
        // \f2free the lhs, destroying pointers if appropriate\fP
        if (--*refptr == 0) {
                delete refptr;
                delete p;
        }

        // \f2copy in values from the right-hand side\fP
        refptr = rhs.refptr;
        p = rhs.p;
        return *this;
}

template<class T> Ptr<T>::~Ptr()
{
        if (--*refptr == 0) {
                delete refptr;
                delete p;
        }
}
#endif
ตฌกฐ๋ฅผ šฉ•„œ Student_info๋ฅผ ž‘„•˜๋Š” ฒฝšฐ šฐ๋ฆฌ๋Š” ƒˆ๋กœ ด๋ž˜Šค— ๋Œ€•„œ ž‘„•  ฝ”๋“œฐ€  „˜€—†๋‹ค.
™œ๋ƒ•˜๋ฉด Student_info— ๋Œ€•„œ ๋‚ด๋ถ€ ฒด๋ฅผ ๋ณ€ฒฝ•˜๋Š” •ˆ˜๋Š” ˜ง readธ๋ฐ šฐ๋ฆฌ˜ ฒฝšฐ—๋Š” read •ˆ˜ ˜œ‹œ ธฐกด˜ ๋‚ด๋ถ€ ๋ฉค๋ฒ„๋ฅผ †Œ๋ฉธ‹œ‚ค , ๋‹‹œ ฒด๋ฅผ ๋งŒ๋“ค–ด„œ • ‹•˜ธฐ ๋•Œ๋ฌธด๋‹ค.
~cpp 
Student_info s1;
s1.read(cin);
Student_info s2 = s1;
s2.read(cin)
ธ๋Ÿฐ๋ฐ ๋‚ด๋ถ€ฒดธ Ptr •ธ๋“ค€ š”†Œ๋ฅผ ๋‚˜ƒ€๋‚ด๋Š” •ธ๋“ค˜ง 1œฒฝšฐฐ€ •„‹ˆ๋ฉด ๋Œ€ƒ˜ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ • œ •˜ง€ •Šธฐ ๋•Œ๋ฌธ— •„๋ž˜™€ ฐ™€ ฝ”๋“œ—„œ s1, s2˜ ฐ’˜ ๋ณ€™”ฐ€ ƒ˜˜–ฅ„ ๋ฏธ˜ง€ •Š๋Š”๋‹ค.

˜œ ฒด˜ ๋ณ€™”ฐ€ ฐ™€ š”†Œ๋ฅผ ฐ€๋ฆฌ‚ค๋Š” •ธ๋“ค๋“ค—ฒŒ ˜–ฅ„ ฃผง€•Šธฐ๋ฅผ ๋ฐ”๋ผ๋Š” regrade •ˆ˜
~cpp 
void Student_info::regrade(double final, double thesis) {
	cp.make_unique();

	if(cp)
		cp->regrade(final, thesis);
	else throw run_time_error("regrade of unknown student");
}

1.4. 14.4 An improvement on controllable handles

~cpp 
//Str.h - ˜ธฐฐ€ €ฐฎ•„„œ ธ๋ƒฅ ๋ณต‚ฌ•จ. -_-
#ifndef GUARD_Str_h
#define GUARD_Str_h

#include <algorithm>
#include <iostream>
#include "Ptr.h"
#include "Vec.h"

template<>
Vec<char>* clone(const Vec<char>*);

// does this version work?
class Str {
	friend std::istream& operator>>(std::istream&, Str&);
	friend std::istream& getline(std::istream&, Str&);

public:
	Str& operator+=(const Str& s) {
		data.make_unique();
		std::copy(s.data->begin(), s.data->end(),
		          std::back_inserter(*data));
		return *this;
	}

	// interface as before
	typedef Vec<char>::size_type size_type;

	// reimplement constructors to create `Ptr's
	Str(): data(new Vec<char>) { }
	Str(const char* cp): data(new Vec<char>)  {
		std::copy(cp, cp + std::strlen(cp),
		          std::back_inserter(*data));
	}

	Str(size_type n, char c): data(new Vec<char>(n, c)) { }
	template <class In> Str(In i, In j): data(new Vec<char>) {
		std::copy(i, j, std::back_inserter(*data));
	}

	// call `make_unique' as necessary
	char& operator[](size_type i) {
		data.make_unique();
		return (*data)[i];
	}
	const char& operator[](size_type i) const { return (*data)[i]; }
	size_type size() const { return data->size(); }

	typedef char* iterator;
	typedef const char* const_iterator;

	iterator begin() { return data->begin(); }
	const_iterator begin() const { return data->begin(); }

	iterator end() { return data->end(); }
	const_iterator end() const { return data->end(); }

private:
	// store a `Ptr' to a `vector'
	Ptr< Vec<char> > data;
};
// as implemented in 12.3.2/216 and 12.3.3/219 
std::ostream& operator<<(std::ostream&, const Str&);
Str operator+(const Str&, const Str&);
inline bool operator<(const Str& lhs, const Str& rhs)
{
        return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
}
inline bool operator>(const Str& lhs, const Str& rhs)
{
        return std::lexicographical_compare(rhs.begin(), rhs.end(), lhs.begin(), lhs.end());
}
inline bool operator<=(const Str& lhs, const Str& rhs)
{
        return !std::lexicographical_compare(rhs.begin(), rhs.end(), lhs.begin(), lhs.end());

}
inline bool operator>=(const Str& lhs, const Str& rhs)
{
        return !std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());

}
inline bool operator==(const Str& lhs, const Str& rhs)
{
        return lhs.size() == rhs.size() &&
                std::equal(lhs.begin(), lhs.end(), rhs.begin());
}
inline bool operator!=(const Str& lhs, const Str& rhs)
{
        return !(lhs == rhs);
}
#endif
ธฐ๋ณธ „Ž˜Šค๋Š”  „˜ Strณผ ๋™•˜ง€๋งŒ ž๋ฃŒตฌกฐฐ€ Ptr< Vec<char> > ˜•œผ๋กœ  •˜๋˜—ˆธฐ ๋•Œ๋ฌธ—  „ฒด ธ ๋ฉ”†Œ๋“œ˜ „ธ๋ถ€ ตฌ˜„ด ๋งŽด ๋ณ€ฒฝ๋˜—ˆ๋‹ค. ธ๋ฆฌ  Ptr…œ”Œ๋ฆฟœผ๋กœ ž๋ฃŒตฌกฐ๋ฅผ ๋‹ค๋ฃธœผ๋กœ„œ Strด๋ž˜Šคฐ€ ๋™•œ ฒด๋ฅผ ฐ€๋ฆฌ‚ฌ ˆ˜ žˆ๋Š” ธฐ๋Šฅ„  œณต•œ‹ค.

1.4.1. 14.4.1  œ–ด•  ˆ˜ —†๋Š” ƒ€ž… ๋ณต‚ฌ•˜ธฐ


~cpp 
template<class T> void Ptr<T>::make_unique() {
	if(*refptr != 1) {
		--*refptr;
		refptf = new size_t(1);
		p = p? p->clone() : 0;
	}
}
 
ตฌ˜„„ œ„•„œ๋Š” Vec::clone()ฐ€  •˜๋˜–ด žˆ–ด••˜ง€๋งŒ, •ˆ˜๋ฅผ  •˜•˜ฒŒ ๋  ฒฝšฐ ›๋ž˜ Vec˜ ตฌ˜„‘œค€ •ˆ˜ vector˜ ตฌ˜„˜ ๋ถ€๋ถ„ด๋ผ๋Š” ฐ€ •—„œ œ„๋ฐฐ๋˜ธฐ ๋•Œ๋ฌธ— ถ”ฐ€•  ˆ˜๋Š” —†๋‹ค.
ด๋ฅผ •ฒฐ•˜ธฐ œ„•„œ šฐ๋ฆฌ๋Š”  „—ญ•ˆ˜ธ clone()๋ฅผ ๋งŒ๋“ค–ด„œ •ฒฐ•œ‹ค. (†Œ”„Šธ›จ–ด ณต•™—„œ๋Š” •œ‹„๋ฅผ šฐšŒ•˜๋ฉด ๋ชจ๋“  ๋ฌธ œฐ€ •ฒฐ๋œ‹ค๋ผ๋Š” ๋งžˆ๋Š”๋ฐ —ฌธฐ—  šฉ๋  ˆ˜ žˆ๋‹ค,)
~cpp 
template<class T> void Ptr<T>::make_unique() {
	if(*refptr != 1) {
		--*refptr;
		refptf = new size_t(1);
		p = p? clone() : 0;
	}
}
 

::clone()˜ ตฌ˜„
~cpp 
template<> Vec<char*> clone(const Vec<char>* vp) {
	return new Vec<char>(*vp);
}
 
…œ”Œ๋ฆฟ˜ ตฌฒด™”(template specialization)
template<>๋ฅผ ‚ฌšฉ•˜๋ฉด Šน • ž ƒ€ž…— ๋Œ€•œ Šน • …œ”Œ๋ฆฟ •ˆ˜˜ ๋ฒ„ „„  •˜•œ‹ค.
ด๋ ‡ฒŒ ๋งŒ๋“ค–ด„ •ˆœ๋А ๋งŒ•ฝ Vec<char>*ฐ€ ž๋กœ ˜ค๋Š” ฒฝšฐ—๋Š” ฒƒ‹–‰๋˜ ‹ค๋ฅธ ๋ฒ„ „˜ …œ”Œ๋ฆฟ˜ค๋Š” ฒฝšฐ—๋Š” ฒด˜ clone()๋ฒ„ „„ ‹–‰•˜ฒŒ ๋œ‹ค.

ด๋Ÿฌ•œ ‚ฌ•„ 𔕕˜๋ฉด ๋‹Œณผ ฐ™๋‹
* Ptr<T>::make_unique()๋ฅผ ‚ฌšฉ•˜ง€ •Š๋Š”๋‹ค๋ฉด T::clone€ ๋ถˆ•„š”
* Ptr<T>::make_unique๋ฅผ ‚ฌšฉ•œ‹ค๋ฉด T::cloneฐ€ žˆ๋‹ค๋ฉด T::clone„ ‚ฌšฉ•  ฒƒด๋‹ค.
* Ptr<T>::make_unique๋ฅผ ‚ฌšฉ•œ‹ค๋ฉด T::cloneฐ€ ๋ฏธ •˜๋˜—ˆ๋‹ค๋ฉด clone<T>๋ฅผ  •˜•„œ ›•˜๋Š” ๋ฐ”๋ฅผ –ป„ ˆ˜ žˆ๋‹ค.

1.4.2. 14.4.2 –ธ œ ๋ณต‚ฌฐ€ •„𔕠นŒš”?

๋งŒ•ฝ const ฒด๋ฅผ †ต•„œ operator[]๋ฅผ †ต•„œ  ‘•œ‹ค๋ฉด ฒด˜ ๋‚ดšฉ„ ๋ฐ”พธ๋Š” ฒƒ„ —ˆšฉ•„œ๋Š” •ˆ๋œ‹ค.
ด๋Ÿดฒฝšฐ operator[] const๋ฅผ †ต•„œ ๋ฆฌ„ด๋˜๋Š” ฐ’€ make_unique๋ฅผ †ต•„œ ๋ณต‚ฌ๋œ ฒƒ„ ๋ฆฌ„•œผ๋กœ„œ ›๋ณธ ฒด˜ ๋ฐ„˜ ๋ณ€˜•„ ๋ฐฉง€•˜๋Š” ฒƒฐ€๋Šฅ•˜‹ค.

Valid XHTML 1.0! Valid CSS! powered by MoniWiki
last modified 2021-02-07 05:22:24
Processing time 0.0359 sec