카테고리 없음

[data structures with c++] std vector 4. changing the vector size

Dalcomi20 2021. 6. 26. 16:58

accessor 로 index를 통해 접근하는 것은 구현했지만.

아직 [ ](subscript operator) 는 구현하지 않았다. 

일단 거기서부터 시작하자.

 

class definition의 public member로 []를 재정의한다.

#overloading []operator.

double& operator [](int n) { return &elem[n] };

굳이 reference를 return 하는 것은 

vec[0] = 1; 과 같은 표현을 allow하기 위함이다.

 

그리고 []operator가 const로 선언된 vector에 대해서도 적어도 값을 읽는데 사용될 수 있도록,

value만 물어다주는 rvalue - 전용 accessor 하나를 더 만들어준다.

 

#const vector accessor

double operator [](int n) const { return elem[n] };

정말 함정이 차고 넘친다;;

조심 조심하며 진행해야 한다.

 

이제 vector에 element를 추가하고 지우는 것을 구현한다.

이 operation들은 vector의 길이를 변화시킨다.

하나의 element를 추가하면, 그만큼의 메모리를 더 할당받아야 된다.

어떻게 이것을 구현할까?

 

아래 코드는 앞선 포스트에서 작성된 것들에 추가하는 식으로 진행된다. 

#defining space

class vector {
  int sz;
  double* elem;
  int space; //number of elements + free space(slots) for new elements.
}

#update the default constructor and add a function that returns available space.

vector::vector() :sz{0}, elem{nullptr}, space{0} { }
int vector::capacity() const {return space;}

# reserve()

void vector::reserve(int newalloc)
{
  if(newalloc <= space) return; //will be using only to increase size
  double *p = new double[newalloc]; //allocates new space.
  for (int i=0; i<sz; ++i) p[i] = elem[i]; //copy old elements.
  delete[] elem;
  elem = p;
  space = newalloc; //update space to new size.
}

reserve 라는 이름에 걸맞게, sz 다음의 빈 공간은 initialize 조차 안한다.

단지 그 위치를 쓰겠다고 찜만 해놓은 것이다.

 

#resize

resize는 vector의 size를 변경한다. capacity는 size가 늘어났을 경우에만 바뀐다.

size가 늘어났을 경우 0으로 초기화한다.

void vector::resize(int newsize)
{
  reserve(newsize); //this deals with the memory
  for(int i=sz; i<newsize; ++i) elem[i] = 0; //init to 0
  sz = newsize;
}

#push_back

void vector::push_back(double d)
{
  if(space==0)
    reserve(8); //if empty vector, allocate 8 spaces to start with.
  else if(sz==space)
    reserve(2*space); //공간을 다 써버렸다. 지금 크기만큼의 공간을 더 받아온다.
  elem[sz] = d;
  ++sz;
}

코드를 보면, 하나 추가되면 공간 하나받고, 또하나 추가되면 하나 더.. 이런 식이 아니라

아예 늘릴때 화끈하게 기존에 32칸을 썼으면 64칸으로 늘려버린다.

이러한 전략이 자주 메모리를 allocate하는 것을 막을 수는 있겠는데,,

65칸만 쓰려고 한다면 조...금 아깝지?

 

Assignment

앞에서 copy-assignment를 구현했었다.

이제 그것을 space까지 포함하여, 약간 정제한다.

 

vector& vector::operator=(const vector& a)
{
  if(this == &a) return *this; //self-assignment.
  if(a.size <= space){//enough space
    for(int i=0; i < a.sz; ++i) elem[i] = a.elem[i]; //copy elements.
    sz = a.sz;
    return *this;
  }
  //this portion runs only if more space is needed.
  double* p = new double[a.sz];
  for(int i=0; i < a.sz; ++i) p[i] = a.elem[i]; //copy elements to p
  delete[] elem;
  space = sz = a.sz; //update space as well.
  elem = p;
  return *this;
}