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