U E D R , A S I H C RSS

AcceleratedC++/Chapter11

1. Chapter 11 Defining abstract data types

3장�서 작성한 Student_info 타입� 복사, 대입, 소멸시� 어떤 �� 수행�는지 명세�어있지 않�.
실제로 �래스를 제작할 경우�는 �래스� �성, 복사, 대입, 소멸� 고려하여 설계�어야한다.
�장�서는 STL vector�래스� 약� 버전� 만들어 보면서 �반�� 형태� �료형� 만드는 방�� �힌다.

1.1. 11.1 The Vec class

�래스를 설계할때�는 우선 �터페�스를 결정해야한다. �터페�스� 결정�는 실제로 그 �체를 �용한 프로그램� 작성해보는 것� 좋다.
~cpp 
//vector �성
vector<Student_info> vs;
vector<double> v(100);

//vector가 사용하는 타입� �르� 얻는다.
vector<Student_info>::const_iterator b, e;
vector<Student_info>::size_type i = 0;

//vector� �요소를 살펴보기 위해, size � index 연산�를 사용
for(i = 0; i != vs.size(); ++1)
	cout<<vs[i].name();

//첫번재 요소와 마지막 요소� 대한 반복� 리턴
b=vs.begin();
e=vs.end();
��� 것들� �장�서 구현할 vector � clone 버전� Vec �래스를 구현할 메소드들�다.

1.2. 11.2 Implementing the Vec class

1.2.1. 11.2.1 메모리 할당

연산� 결정한후�는 어떤 방�으로 Vec를 구현할지를 결정하는 것�다.
여기서는 template class를 �용한다.
템플릿� 함수�만 아니� �래스�서� 사용하는 것� 가능하다.
~cpp 
template <class T> class Vec {
public:
	//interface
private:
	//implementation
};
 
begin, end, size 함수를 구현해야 하므로 �러한 작업� 위해서 첫 요소� 주소, 마지막 요소를 하나 지난 주소, 요소들� 개수를 저장할 수 있어야한다.
size는 begin, end 를 통해서 그 �기를 구하는 것� 가능하므로 여기서는 첫 요소� 주소, 마지막 요소를 하나 지난 주소를 저장하고 개수는 계산� 통해서 구현한다.
~cpp 
template <class T> class Vec {
public:
	//interface
private:
	T* data;	// 첫번째 요소
	T* limit;	// 마지막 요소�서 하나를 지난 곳� ��터
};
 
템플릿� 단지 틀� ��며, 사용할때 type parameter로 준 형� 따�서 실제� �래스를 �성한다.
따�서 어떤 타입� Vec�서 사용�는진는 정�부가 instiation �기 전�는 알 수 없다.

1.2.2. 11.2.2 �성�(Constructor)

앞� �터페�스 명세�서 아래� 2가지를 가능하게 하�� 했기 때문� �성� 2개는 최소한 구현해야한다.
~cpp 
Vec<Student_info> vs;		// default constructor
Vec<Student_info> vs(100);	// Vec� 요소� �기를 취하는 �성�
				// 표준 vector �래스는 �기와 함께 초기화 요소를 ��로 받는 �성�� 제공한다.
 

~cpp 
template <class T> class Vec {
public:
	Vec() { create(); }	// 아�으로선� 구현부분�서 정해진 것� 없기 때문� 임시�으로 함수를 만들어서 넣었다.
	explicit Vec(size_type n, const T& val = T()) { create(n, val); }
private:
	T* data;	// 첫번째 요소
	T* limit;	// 마지막 요소�서 하나를 지난 곳� ��터
};
 
2번째 �성�는 초기화� ��로 �� 파�메터� T� �성�를 �용한다.
��� 기본형� 지정해주면 한개� 함수정�로� 2가지� �성�� 역할� 할 수 있기 때문� 편리하다.
explicit 키워드
�성�가 하나� ��를 받는 경우. �반�� 대입 �성�와 혼용� � 가능성� 존재하기 때문� 명시�� �성만� 허용시키는 방법�다. (12.2 절�서 �세한 논�)
~cpp 
Vec<int> vi(100);	// Working. int 를 통해 명시�� �성
Vec<int> vi = 100;	// not working. 암묵�으로 Vec를 �성하고 그 값� vi � 복사한다. refer 11.3.3
 

1.2.3. 11.2.3 타입 정�

const_iterator, iterator를 정�해야함.
back_inserter(T)함수를 통해서 ��으로 �기를 변경시키기 위해서 value_type, push_back 타입� 정�함. (value_type � 현재 저장� 요소가 어떤 타입�지를 알려줌)
list� 반복�를 구현하는 경우�면 ++ 연산� 통해서 노드로 연결� 다� 노드를 리턴하는 함수를 오버로딩해야하나, 여기서는 배열� 요소를 가리키므로 단순� ��터를 리턴하는 것 만으로 우리는 임� 접근 반복�를 구현하는 것� 가능하다.

value_type� T가 �어야하는 것� 당연하다. 배열� 개수를 표현하는 size_type� cstddef � 존재하는 size_t로서 정�하는 것� 합당하다.

~cpp 
template <class T> class Vec {
public:
	typedef T* iterator;
	typedef const T* const_iterator;
	typedef size_t size_type;
	typedef T value_type;

	Vec() { create(); }	// 아�으로선� 구현부분�서 정해진 것� 없기 때문� 임시�으로 함수를 만들어서 넣었다.
	explicit Vect(size_type n, const T& val = T()) { create(n, val); }
private:
	iterator data;	// 첫번째 요소
	iterator limit;	// 마지막 요소�서 하나를 지난 곳� ��터
};
 
절�한 typedef를 추가하고, 멤버 ��터� 형� 여기� 맞추어서 변경하였�.

1.2.4. 11.2.4 ��스 � size


~cpp 
for (i = 0; i != vs.size(); ++)
	cout<<vs[i].name();
 
�기� 연산� 가능하게 하기 위해서는 operator[], size() 함수를 정� 해야한다.

연산� 오버로딩(operator overload)
오버로드 연산�� 명칭� operatorop � 형태로 나타난다. 즉 ~cpp []� 경우�는 ~cpp operator[]로 나타낼 수 있다.
만약 오버로드 연산�가 멤버함수가 아니�면(friend 함수) 좌측 피연산�는 첫번째 �수, 우측 피연산�는 �번재 �수로 나타낼 수 있다.
만약 멤버 함수로 ì—°ì‚°ìž�ê°€ ì •ì�˜ ë�˜ì–´ 있다면 좌측 피연산ìž�는 함수를 호ìœí•œ ê°�체로 간주ë�˜ê³  오버로드 ì—°ì‚°ìž�는 ì�¸ìž�로 우측ì�˜ 피연산ìž�ë§Œì�„ ì�¸ìž�로 취한다.
~cpp []연산� ��로 size_type� 취하고, 리턴값으로 value_type� 레�런스를 취해야할 것�다.
~cpp 
template <class T> class Vec {
public:
	typedef T* iterator;
	typedef const T* const_iterator;
	typedef size_t size_type;
	typedef T value_type;

	Vec() { create(); }	// 아�으로선� 구현부분�서 정해진 것� 없기 때문� 임시�으로 함수를 만들어서 넣었다.
	explicit Vect(size_type n, const T& val = T()) { create(n, val); }

	size_type size() const { return limit - data; }

	T& operator[](size_type i) { return data[i]; }
	const T& operator[](size_type i) const { return data[i]; };	// �경우�� 레�런스를 쓰는 �유는 성능�� �유때문�다.
private:
	iterator data;	// 첫번째 요소
	iterator limit;	// 마지막 요소�서 하나를 지난 곳� ��터
};
 
operator[] � 2가지 버전� 오버로딩 할 수 잇는 근거
모든 멤버함수는 암묵ì �으로 한가지ì�˜ ì�¸ìž�를 ë�” 받는다. 그것ì�€ ê·¸ 함수를 호ìœí•œ ê°�ì²´ì�¸ë�°, ì�´ê²½ìš° ê·¸ ê°�ì²´ê°€ constì�´ê±°ë‚˜ const ê°€ 아닌 버전 2가지가 존재하는 것ì�´ 가능하기 때문ì—� parameter specification ì�´ ë�™ì�¼í•˜ì§€ë§Œ 오버로딩ì�´ 가능하다.

1.2.5. 11.2.5 반복�를 리턴하는 연산


~cpp 
template <class T> class Vec {
public:
	typedef T* iterator;
	typedef const T* const_iterator;
	typedef size_t size_type;
	typedef T value_type;

	Vec() { create(); }	// 아�으로선� 구현부분�서 정해진 것� 없기 때문� 임시�으로 함수를 만들어서 넣었다.
	explicit Vect(size_type n, const T& val = T()) { create(n, val); }

	size_type size() const { return limit - data; }

	T& operator[](size_type i) { return data[i]; }
	const T& operator[](size_type i) const { return data[i]; };	// �경우�� 레�런스를 쓰는 �유는 성능�� �유때문�다.

	//반복�들� 리턴하는 새로운 함수들
	iterator begin() { return data; }
	const_iterator begin() const { return data; }

	iterator end() { return limit; }
	const_iterator end() const { return limit; }

private:
	iterator data;	// 첫번째 요소
	iterator limit;	// 마지막 요소�서 하나를 지난 곳� ��터
};
 

1.3. 11.3 Copy control

우리가 복사, 대입, 소멸시 하는 �� 대해서 명시�으로 정하지 않으면 컴파�러는 정해진 �신만� 방법으로 �런 �� 하는 정�를 만들어서 작�하게 �다.
사실 �렇게 �세한 �체� 행�양�� 규제할 수 잇는 언어로는 C++� 유�하다. (그만� �래스를 작성할때 많� 것들� 고려�어야한다.)

1.3.1. 11.3.1 Copy �성�

implicit copy constructor
~cpp 
vector<int> vi;
double d;
d = median (vi);		// copy constructor work

string line;
vector<string> words = split(words);	// copy constructor work
 

explicit copy constructor
~cpp 
vector<Student_info> vs;
vector<Student_info> v2 = vs;	// copy constructor work (from vs to v2)
 
복사 �성�
복사 ìƒ�성ìž�는 ìƒ�성ìž�ì�˜ ì�´ë¦„ì�€ 기타 ìƒ�성ìž�와 같으나 ì�¸ìž�로 ìž�ì‹ ì�´ 호ìœë�œ ê°�ì²´ì�˜ 타입ì�„ 갖는 ìƒ�성ìž�를 ì�˜ë¯¸í•œë‹¤.
함수� ��를 복사하는 것� �함해서, 복사본� 만든다는 �미를 정�하고 있기 때문� 매개변수를 레�런스 타입으로 하는 것� 좋다.
~cpp 
template <class T> class Vec {
public:
	Vec(const Vec& v);	// copy constructor
	// �전과 같�
};
 

보통 디�트 복사 �성�� 경우�는 �래스� 멤버 변수들� 단순히 복사만 하게 �니다. �때 만약 그 멤버 변수가 ��터� 형태�고 한다면 문제가 발�하게 �다.
� 경우 한쪽� �체가 수정�거나 소멸�면 �를 복사한 �체� 그 �향� 받게�기 때문�다.
따�서 ��터� 경우 새로운 주소 공간� 할당받고 그 대�� �는 값� 복사해야지 �런 문제가 발�하지 않는다.
역시 다른 �성�와 마찬가지로 create() 함수를 �용해서 복사를 행하�� 만든다.
~cpp 
template <class T> class Vec {
public:
	Vec(const Vec& v) { create(v.begin(), v.end() ); }	// copy constructor
	// �전과 같�
};
 

1.3.2. 11.3.2 대입(Assignment)

대입 연산�(assignment operator)
operator=() � 여러가지 �스턴스중�서 ��로 �신� �래스 형 �체� 대한 const 레�런스를 취하는 형태를 대입연산�� 칭한다.
리턴값� C++ 기본 대입연산�와� �관성� 유지를 위해서 연산�� 외쪽항(left-hand side)�대한 레�런스를 취한다.
~cpp 
template <class T> class Vec {
public:
	Vec& operator=(const Vec&);	// copy constructor
	// �전과 같�
};
 
대입 연산� 오버로딩시 주�해야할 사항
대입 연산�는 복사 연산�와 달리 왼쪽항� 제거하고 새로운 값으로 대체시킵니다. 복사 �성�는 수행 시�� 왼쪽항� �체가 처� 만들어진 �태�기 때문� 해제할 대�� 없지만, 대입 연산�는 기존��터가 있는 �태�서� 대입� 할 수 있기 때문� 복사 �성�와 비슷하게 구성�어야 한다.
�한 �기 대입 (self-assignment)� 위한 고려가 필요하다.
~cpp 
template<class T> Vec<T>& Vec<T>::operator=(const Vec& rhs) {
	// self-assignment check
	if (&rhs != this) {
		//lhs memory deallocation
		uncreate();
		create(rhs.begin(), rhs.end());
	{
	return *this;
}
 
  • í—¤ë�”파ì�¼ì—�서ì�˜ 리턴타입ì�´ Vec& 로 사용ë�˜ì—ˆì�Œ
    템플릿� 스코프 안�서는 타입 매개변수를 �략하는 �� � 쉬운 표현� 사용할 수 있다.
    Vec::operator= � 아니�, Vec<T>::operator= 가 �래� �름�다. 그러나 �단 operator=가 Vec<T>� 멤버�는 사실� �혀지면 ��� 템플릿 한정�를 반복할 필요가 없다.
  • this 키워드ì�˜ 사용
    this는 멤버함수 안ì—�서 유효하다. this는 멤버함수를 호ìœì‹œí‚¨ ê°�ì²´ì�˜ í�¬ì�¸í„°ë¥¼ 리턴한다.
    만약 this 키워드로 �기 대입 체�를 하지 않� 경우�는 오른쪽 �체를 해제한 뒤� 다시 왼쪽항� 대입하게 �므로 문제가 발�하게 �다.
  • *this ì�˜ 리턴
    지역 �체� 대한 리턴� 해서는 안�다. 지역 �체를 리턴하면 �체� 존재 scope를 벗어나기 때문� 올바른 �작� 보장하지 못한다.

1.3.3. 11.3.3 대입� 초기화가 아니다

C++� = 가 �체� 초기화, 복사 시� ��하게 사용�기 때문� 복사 �성�와, 대입연산�� 구분� 없다.
= 가 초기화 �지 않� �체� 사용�면 복사 �성�로, 초기화� �체� 사용�면 대입 연산�로 사용�다.
초기화 �황 * 변수 선언시
* 함수 진입시, 함수 매개변수
* 함수 리턴값
* �성� 초기 설정�

�성�� 2가지 용법
~cpp 
string url_ch = "~;/?:@=&$-_.+!*'(),";
string spaces(url_ch.size(), ' ');
 

리턴값�서� 복사 �성�� 사용, 대입연산�� 사용
~cpp 
vector<string> split(const string&);
vector<string> v;
v = split(line);	// 함수� 종료시 임시 �체를 복사�성�로 �성
			// �성� 임시 �체를 대입 연산�가 v � 대입
 

1.3.4. 11.3.4 소멸�(Destructor)

소멸�(destructor)
�� 할당으로 �성� �체는 delete 키워드로 제거하기 전�는 메모리 공간�서 삭제�지 않는�, �체 멤버변수로 �� 할당� � 변수가 존재한다면 �체� 해제시� � 공간� 메모리�서 해제해주어야 한다.
소멸�� 형태는 �성�와 마찬가지로 반환형� 없으며 �체 형명과 ��한 함수명� 갖는 대신� 첫 글�로 ~를 가져야 한다.
~cpp 
template <class T> class Vec {
public:
	~Vec() { uncreate; }	// copy constructor
	// �전과 같�
};
 

1.3.5. 11.3.5 디�트 연산(Default operation)

�성�, 소멸�, 복사 �성�, 대입연산�를 재정� 하지 않� 경우�는 컴파�러가 기 정�� 방�으로 �런 �성�� 기본형� 만든다.
� 경우 멤버 �체(has-a)� 경우�는 재귀�으로 �런 디�트 연산� 수행하며, 기본형(primitive type)� 경우�는 값��한 방�으로 �런 연산들� 행해진다. 그러나 ��터� 경우 특별히 다른 �� 잃어나지 않으며, ��터가 가리키� 공간� 해제�지 않는다.
default constructor 를 사용하기 위해서는 �체� 멤버들� 디�트 �성�를 가진 경우�만 정��� �작� 보장할 수 있다.
�반�으로는 명시�으로 정�� 디�트 �성�를 만드는 것� 좋다.

1.3.6. 11.3.6 세 법칙(rule of three)

복사 �성� 미정� �본과 복사본� ��터가 �호 참조� 형�으로 �작한다.
소멸� 미정� ��터 �체가 존재하는 경우 memory leak � 발�
※ �래스� 소멸�가 필요하다면 반드시 복사 �성�와 대입 연산�를 재정�해야 올바른 �작� 보장한다.

한 �체� 대해서 모든 복사본� 제대로 �작하면 재정� 해야할 것들
T::T()
T::~T()
T::T(const T&)
T::operator=(const T&)

Rule of three : 복사 �성�, 소멸�, 대입 연산�가 밀접한 관계를 갖는 것� �컬어 표현하는 ��다.

1.4. 11.4 Dynamic Vecs

push_back� 구현방�
push_back� 구현함� 있어서 요소 배열� �기를 키워야하는� � 것� 위해서 여기서는 필요양 보다 많� 수� 배열� 할당하고 하나씩 변수를 하나� 만들어서 현재 사용가능한 �� 가리키는� �용하기로 한다.
~cpp 
template<class T> class Vec {
public:
	size_type size() const { return avail - data; }
	iterator end() { return avail; }
	const_iterator end() const { return avail; }
	void push_back(const T& val) {
		if (avail == limit)
			grwo(0;
		unchecked_append(val);
	}
private:
	iterator data;
	iterator avail;
	iterator limit;
}

1.5. 11.5 Flexible memory management

Vec�서 new, delete 키워드를 사용하지 않는다. 배열� new로 할당하게 �면 기본�으로 �성�는 �체� 디�트 �성�로 초기화 �기 때문�다. �는 �래 우리가 ��한 것과는 다른 방�으로 �작한다.
따�서 우리는 좀� �반�� 형태� 표준 제공 ��브러리� 존재하는 관리�를 사용한다.

<memory> � allocate<> STL�서 알아야할 중요 메소드
~cpp 
template<class T> class allocator {
pubilc:
	T* allocate(size_t);
	void deallocate(T*, size_t);
	void construct(T*, T);
	void destroy(T*);
};
allocate, deallocate 실제 메모리� 공간� 할당, 해제한다. 그러나 할당시 초기화는 하지 않는다.
construct, destroy 할당� 메모리 공간� �당한 ��터 타입� 초기화 시킨다. (공간� allocate를 통해서 �미 할당� 공간�어야 한다.)

allocate �래스� 비멤버 함수 �부
~cpp 
template<class In, class For> For uninitialized_copy(In, In, For);
tempalte<class for, class T> void uninitialized_fill(For, For, const T&);
uninitialized_copy 첫번째와 �번째��� 스퀀스만�� 3번째 ��� 공간� 복사한다.
uninitialized_fill 첫번째와 �번째 ��� 공간� T로 채운다.

1.5.1. 11.5.1 최종 Vec �래스


~cpp 
//vec.h
#ifndef VEC_H
#define VEC_H

#include <algorithm>
#include <cstddef>
#include <memory>

using std::max;

template <class T> class Vec {
public:
	typedef T* iterator;
	typedef const T* const_iterator;
	typedef size_t size_type;
	typedef T value_type;
	typedef T& reference;
	typedef const T& const_reference;

	Vec() { create(); }
	explicit Vec(size_type n, const T& t = T()) { create(n, t); }

	Vec(const Vec& v) { create(v.begin(), v.end()); }
	Vec& operator=(const Vec&);	// as defined in 11.3.2/196
	~Vec() { uncreate(); }

	T& operator[](size_type i) { return data[i]; }
	const T& operator[](size_type i) const { return data[i]; }

	void push_back(const T& t) {
		if (avail == limit)
			grow();
		unchecked_append(t);
	}

	size_type size() const { return avail - data; }  // changed

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

	iterator end() { return avail; }                 // changed
	const_iterator end() const { return avail; }     // changed
	void clear() { uncreate(); }
	bool empty() const { return data == avail; }

private:
	iterator data;	// first element in the `Vec'
	iterator avail;	// (one past) the last element in the `Vec'
	iterator limit;	// (one past) the allocated memory

	// facilities for memory allocation
	std::allocator<T> alloc;	// object to handle memory allocation

	// allocate and initialize the underlying array
	void create();
	void create(size_type, const T&);
	void create(const_iterator, const_iterator);

	// destroy the elements in the array and free the memory
	void uncreate();

	// support functions for `push_back'
	void grow();
	void unchecked_append(const T&);
};

template <class T> void Vec<T>::create()
{
	data = avail = limit = 0;
}

template <class T> void Vec<T>::create(size_type n, const T& val)
{
	data = alloc.allocate(n);
	limit = avail = data + n;
	std::uninitialized_fill(data, limit, val);
}

template <class T>
void Vec<T>::create(const_iterator i, const_iterator j)
{
	data = alloc.allocate(j - i);
	limit = avail = std::uninitialized_copy(i, j, data);
}

template <class T> void Vec<T>::uncreate()
{
	if (data) {
		// destroy (in reverse order) the elements that were constructed
		iterator it = avail;
		while (it != data)
			alloc.destroy(--it);

		// return all the space that was allocated
		alloc.deallocate(data, limit - data);
	}
	// reset pointers to indicate that the `Vec' is empty again
	data = limit = avail = 0;

}

template <class T> void Vec<T>::grow()
{
	// when growing, allocate twice as much space as currently in use
	size_type new_size = max(2 * (limit - data), ptrdiff_t(1));

	// allocate new space and copy existing elements to the new space
	iterator new_data = alloc.allocate(new_size);
	iterator new_avail = std::uninitialized_copy(data, avail, new_data);

	// return the old space
	uncreate();

	// reset pointers to point to the newly allocated space
	data = new_data;
	avail = new_avail;
	limit = data + new_size;
}

// assumes `avail' points at allocated, but uninitialized space
template <class T> void Vec<T>::unchecked_append(const T& val)
{
	alloc.construct(avail++, val);
}

template <class T>
Vec<T>& Vec<T>::operator=(const Vec& rhs)
{
	// check for self-assignment
	if (&rhs != this) {

		// free the array in the left-hand side
		uncreate();

		// copy elements from the right-hand to the left-hand side
		create(rhs.begin(), rhs.end());
	}
	return *this;
}

#endif
 
�래스 불변�(class invariant)
  • data는 첫번째 요소, 없다면 0ì�„ 가진다.
  • data<=avail<=limit
  • ìƒ�성ë�œ 요소는 [data, avail)ì�˜ 범위ì—� 존재
  • ìƒ�성ë�˜ì§€ 않ì�€ 요소는 [avail, limit)ì�˜ 범위ì—� 존재

    ~cpp 
    template <class T> void Vec<T>::create()
    {
    	data = avail = limit = 0;	// 디�트 �성� �기 때문� ��터� ���터를 넣어서 빈 �체임� 나타낸다.
    }
    
    template <class T> void Vec<T>::create(size_type n, const T& val)
    {
    	data = alloc.allocate(n);	// ��로 받� 만�� 공간� 할당한다.
    	limit = avail = data + n;	// �� 가리킨다. 현재로서는 초기화시 n개� 공간� 할당했기 때문� avail = limit �다.
    	std::uninitialized_fill(data, limit, val);	// 아� 초기화 �지 않� 공간� 여러개� �체를 삽입해야하기 때문� 비멤버함수를 �용해서 초기화 시킨다.
    }
    
    template <class T>
    void Vec<T>::create(const_iterator i, const_iterator j)
    {
    	data = alloc.allocate(j - i);
    	limit = avail = std::uninitialized_copy(i, j, data);
    }
     
    주�� 참고하고 �해하기 바람.

    ~cpp 
    template <class T> void Vec<T>::uncreate()
    {
    	if (data) {
    		// destroy (in reverse order) the elements that were constructed
    		iterator it = avail;
    		while (it != data)
    			alloc.destroy(--it);
    
    		// return all the space that was allocated
    		alloc.deallocate(data, limit - data);
    	}
    	// reset pointers to indicate that the `Vec' is empty again
    	data = limit = avail = 0;
    
    }
     
    초기화 �어있는 내부� 요소들� 하나씩 destroy함수를 �용해서 소멸시킨다.
    그후 할당� 공간� deallocate 함수를 �용해서 메모리 공간��서 해제 시킨다.
    해제가 �난 �후�는 다시 빈 백터로 나태내기위해서 data, limit, avail � 초기화 한다.

    ~cpp 
    template <class T> void Vec<T>::grow()
    {
    	// when growing, allocate twice as much space as currently in use
    	size_type new_size = max(2 * (limit - data), ptrdiff_t(1));	// 비어있는 벡터� 경우�는 1개만 할당한다. 
    
    	// allocate new space and copy existing elements to the new space
    	iterator new_data = alloc.allocate(new_size);
    	iterator new_avail = std::uninitialized_copy(data, avail, new_data);
    
    	// return the old space
    	uncreate();
    
    	// reset pointers to point to the newly allocated space
    	data = new_data;
    	avail = new_avail;
    	limit = data + new_size;
    }
    
    // assumes `avail' points at allocated, but uninitialized space
    template <class T> void Vec<T>::unchecked_append(const T& val)
    {
    	alloc.construct(avail++, val);
    }
     
    grow 함수는 한번 호ìœí• ë•Œ ì�´ë¯¸ 워래 공간ì�˜ 2배를 할당시키기 때문ì—� 계ì†�ë�œ push_back로 ì�¸í•œ 메모리 할당 오버헤드를 줄ì�¼ 수 있다.
    unchecked_append()함수는 grow() 함수� 바로 뒤�서만 �작하�� 구성했기 때문� �작� 안정성� 보장할 수 있다. (물론 문서로 남겨서 �후 �래스 확장시 다른 프로그래머가 알 수 있�� 해야할 듯)



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