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.0419 sec