[자료구조] Pointer와 Dynamic Arrays
포인터와 동적 배열
-
동적 배열은 프로그램이 실제로 실행된 후에만 크기가 결정되는 배열이다.
-
C++에서 포인터와 동적 메모리 할당을 사용하여 동적 배열을 구현할 수 있다.
-
포인터는 변수의 메모리 주소다.
-
표인터 변수는 값이 포인터인 변수다.
Syntax:
Type_name *var_name ;
Type_name* var_name ;
Examples:
double *ptr ; // == double* ptr
char *c1_ptr , *c2_ptr ;
// == char* c1_ptr, c2_ptr
포인터 예시
Example:
int i = 42 ;
int j = 80 ;
int *p1, *p2 ;
p1 = &i ; p2 = &j ;
p2 = p1 ;
cout << *p1 << endl ; //42
cout << *p2 << endl ; //42
cout << i << endl ; //42
cout << j << endl ; //80
Example:
int i = 42 ;
int j = 80 ;
int *p1, *p2 ;
p1 = &i ; p2 = &j ;
*p2 = *p1 ;
cout << *p1 << endl ; //42
cout << *p2 << endl ; //42
cout << i << endl ; //42
cout << j << endl ; //42
Dynamic variable
다이나믹 베리어블은 선언되지 않았지만 실행중에 생성되는 프로그램이다.
New 오퍼레이션은 특정 유형의 메모리를 할당하고 이 새로운 동적 변수에 대한 포인터를 반환한다.
Example:
int *p1 ;
double *p2 ;
p1 = new int ;
*p1 = 42 ;
p2 = new double[4] ;
p2[2]=5.5 ;
출력값
delete operator
삭제 오퍼레이터는 변수에 사용된 메모리를 헤제한다.
Example: delete
int *p1 ;
double *p2 ;
p1 = new int ;
*p1 = 42 ;
p2 = new double[4] ;
p2[2]=5.5 ;
delete p1;
delete[ ] p2 ;
출력값
파라미터로서의 포인터와 배열
벨류 파라미터 예시
Example:
void make_it_42(int* i_ptr)
{ *i_ptr = 42 ; }
…
int *main_ptr ;
main_ptr = new int ;
make_it_42(main_ptr) ;
… // 이 뒤로 i_ptr은 더이상 사용할 수 없다.
출력값
배열 파라미터 예시
void make_it_all_42(double data[ ], size_t n)
{ size_t i;
for (i=0;i<n;++i)
data[i]=42 ;
}
…
double main_array[10] ;
make_it_all_42(main_array,10) ;
cout << main_array[5] ; //42
const 파라미터의 예시
bool is_42(const int* i_ptr)
{
return (*i_ptr == 42) ;
}
double average(const double data[], size_t n);
{
size_t i ; double sum ;
assert(n>0) ;
sum = 0 ;
for(i=0; i<n; ++i)
sum += data[i] ;
// data[i] += 1; 을 사용하면 에러가 난다.
return (sum/n) ;
}
레퍼런스 파라미터의 예시
void allocate_doubles(double*& p, size_t& n);
{
cout << “Enter the number of doubles:” ;
cin >> n ;
p = new double[n] ;
}
-
포인터이면서 레퍼런스의 파라미터 : *&
-
때때로 함수는 새 포인터가 새 위치를 가리키도록 포인터 파라미터를 실제로 변경한다.
-
함수 자체에서 만든 배열을 다른곳(main)에서 제어하고 싶을때 포인터레퍼런스 파라미터를 사용한다.
-
함수는 리턴타입이 한 개라 배열이나 다른 타입을 리턴받고 싶을 때 사용한다.
동적배열을 통한 bag class
이전 장에서 다룬 bag class를 포인터를 사용하면 컴파일 시간 이 아닌 런타임 에 크기가 결정되는 데이터 구조를 정의할 수 있다.
The Static Bag:
class bag {
…
value_type data[CAPACITY] ;
size_type used;
}
The Dynamic Bag:
class bag {
…
value_type *data ;
size_type used;
size_type capacity ;
}
동적 가방 클래스를 정의하려면 먼저 constructor을 정의해야 합니다.
bag(size_type init_capacity = Default_Capacity);
bag::bag(size_type init_capacity )
{
data = new value_type[init_capacity]; //중요!
capacity = init_capacity; //중요!
used = 0; // 초기화, 중요!
}
copy constructor
Copy constructor : 소스 오브젝트를 복사해서 새 인스턴스를 생성한다.
bag(const bag& source);
bag::bag(const bag& source)
{
data = new value_type[source.capacity];
capacity = source.capacity;
used = source.used;
copy(source.data, source.data + used, data);
}
bag(const bag& source);
// Data Sharing !!!
bag::bag(const bag& source)
{
data = source.data ;
//이 개체는 소스 개체와 데이터 배열을 공유한다.
capacity = source.capacity ;
used = source.used ;
}
destructor
- frees 동적 메모리
~bag( );
bag::~bag( )
{
delete [ ] data ;
}
함수가 종료되도 다이나믹 배열은 메모리를 놓지 않고 가지고 있다.
따라서 딜리트는 명령어는 할당되어있는 메모리를 시스템에 돌려주라 라는 의미다.
assignment operator “=”
할당 오퍼레이터
- 먼저 할당(a = a)을 확인한다.
- 배열의 크기가 일치하지 않으면 새 배열에 메모리를 할당한다.
- 원본 데이터를 새로 할당된 데이터 배열에 복사한다.
- Copy constructor와 비슷하다.
Example
![]()
![]()
void bag::operator = (const bag& source) {
value_type *new_data;
if (this == &source) //ca[acity 같은지 확인
return;
if (capacity != source.capacity)//만약 다르면
{
new_data = new value_type[source.capacity];
delete [ ] data ;
data = new_data ;
capacity = source.capacity ;
}
used = source.used ;
copy(source.data, source.data+used,data) ;
}
reserve function
Reserve(예약) 기능 : 가방의 용량증가
void bag::reserve(size_type new_capacity)
{
value_type *larger_array ;
if (new_capacity == capacity)
return ;
if (new_capacity < used)
new_capacity = used ;
larger_array = new value_type[new_capacity] ;
copy(data, data+used, larger_array) ;
delete [ ] data ;
data = larger_array ;
capacity = new_capacity ;
}
insert function
Insert (삽입) 기능 : 공간을 확보한다.
void bag::insert(const value_type& entry)
{
if (used == capacity)
reserve(used+1) ;
data[used] = entry ;
++used ;
}
”+” operator
- 두 개의 백을 추가하고 결과를 반환한다.
bag operator +(const bag& b1,const bag& b2)
{
bag answer(b1.size() + b2.size()) ;
answer += b1 ;
answer += b2 ;
return answer ;
}
”+=” operator
- 오브젝트에 새 가방을 추가한다.
void bag::operator +=(const bag& addend)
{
if (used + addend.used > capacity )
reserve(used + addend.used) ;
copy(addend.data, addend.data+addend.used,data+used) ;
used += addend.used ;
}
Notes
클래스의 멤버 변수가 동적 메모리에 대한 포인터인 경우 destructor, copy constructor 및 오버로드 할당 오퍼레이터를 제공해야한다.
댓글남기기