C++ Chapter 7.9 : std::vector를 스택처럼 사용하기

Date:     Updated:

카테고리:

태그:

인프런에 있는 홍정모 교수님의 홍정모의 따라 하며 배우는 C++ 강의를 듣고 정리한 필기입니다. 😀
🌜 [홍정모의 따라 하며 배우는 C++]강의 들으러 가기!


chapter 7. 함수 : std::vector를 스택처럼 사용하기

🔔 std::vector

#include <vector>를 해주어야 사용 가능하다.

std::vector<int> vec{1, 2, 3, 4, 5};
int * v_ptr = new int[5] {1, 2, 3, 4, 5};

vector동적 할당 받아 힙 메모리를 쓰는 것이라서 이렇게 포인터에 직접 new로 동적할당 받는 것과 비슷하다. 저 두 식은 비슷하다. 다만 vector를 사용하면 vector에서 지원해주는 함수들을 사용하여 좀 더 편하게 동적 메모리를 사용할 수 있다.

🔔 vector의 sizecapacity

  • capacity
    • 실제로 메모리를 차지하는 원소 개수
    • 벡터가 실제로 차지하는 메모리 공간
    • 벡터의 여유 메모리 공간과 같다.
    • 원소 추가시 new, delete 없이 capacity 내에서 공간을 땡겨온다.
  • size : capacity 중에서 실 사용 개수
#include <iostream>
#include <vector> // 이게 필요하다

using namespace std;

int main()
{
	std::vector<int> v{ 1,2,3 };

	for (auto &e : v)     // 1 2 3 출력
		cout << e << " ";
	cout << endl;

	cout << v.size() << endl;  // 3 출력

    v.resize(2);  // 벡터의 사이즈를 2로 조정해주면 

    for (auto &e : v)     // 1 2 출력
		cout << e << " ";
	cout << endl;

    cout << v.size() << " " << v.capacity() << endl;  // 2 3 출력

    int * ptr = v.data();

    cout << ptr[2] << endl;  // 3 출력  

	return 0;
}
  • v.resize(2)
    • 벡터 v의 size를 2로 변경했다.
  • v.size()
    • 벡터의 size 리턴
  • v.capacity()
    • 벡터의 capacity 리턴
  • v.data()
    • 벡터가 사용하는 힙 메모리의 주소를 리턴하는 함수
    • 이를 ptr 포인터 변수에 저장
  • ptr[2]
    • size가 2로 변경된 탓에 이제 3번째 원소를 접근할 수 없게 되었지만
    • 힙 메모리의 주소를 받아 ptr[2]로 강제로 3번째 원소에 접근함

image

vector는 빠른 속도를 위하여 resize시에도 new, delete을 자제하는 방향으로 설계되어 있다.

resize(2)로 벡터의 size를 2로 줄였기 때문에 v.at(2)를 하려 하면 런타임 에러가 난다. 즉, 3번째 원소에는 접근이 불가능해지는 것. 3번째 원소는 이제 해당 벡터의 원소가 아니므로 delete되어 메모리가 해제될 것 같지만 사실 해제되지 않고 숨겨져 있다! v.data()를 통해 벡터v의 힙 메모리 주소를 ptr에 리턴받아 ptr[2]해보면 접근 가능하다. 벡터는 delete 하고 new하는 연산을 줄이고 속도를 빠르게 하기 위해 새로운 사이즈 3짜리의 작은 공간으로 이사(new)하고 기존 벡터를 삭제(delete)하는 것이 아닌 아닌 그냥 resize(2)하면 [2]원소는 접근 못하게 막아둘 뿐이다. capacity 값은 3으로 출력되는 것을 보면 size는 2개가 되었더라도 실제로 메모리를 차지하는 원소 개수는 3개라는 것을 알 수 있다.


🔔 vector의 resizereserve

  • resize(n)
    • size를 n으로 변경
  • reserve(n)
    • capacity를 n으로 변경
    • n개의 원소를 담을 수 있을 만큼의 메모리 용량 잡기.
std::vector<int> v {1, 2, 3};
v.resize(10);  // ✨resize✨

for ( auto &e : v)
   cout << e << " ";  // 1 2 3 0 0 0 0 0 0 0 출력
cout << endl;

cout << v.size() << " " << v.capacity() << endl;  // 10 10 출력

벡터v의 size는 10이기 때문에 이 벡터의 실 사용 원소 개수는 10개이다. 따라서 지정된 원소는 3개 뿐이지만 이 벡터의 크기는 10이기 때문에 이 벡터를 순회하여 출력하면 “1 2 3 0 0 0 0 0 0 0”이 출력된다.

std::vector<int> v {1, 2, 3};
v.reserve(1024);  // ✨reserve✨

for ( auto &e : v)
   cout << e << " ";  // 1 2 3 출력
cout << endl;

cout << v.size() << " " << v.capacity() << endl;  // 3 1024 출력

벡터v의 메모리를 1024개의 원소가 들어갈 수 있을 만큼 여유를 늘려준 것 뿐 벡터v의 실제 원소 개수는 여전히 3개다. 이렇게 capacity를 늘려주면 벡터에 원소 추가시 new없이 바로 capacity 내의 여유 메모리에서 공간을 땡겨온다.


🔔 vecotr를 스택처럼 사용하는 법

vector에는 push_back(), pop_back() 함수가 내장되어 있는데 Stack의 push, pop 연산과 비슷하다.

스택을 vector로 쓰는 이유

  1. push, pop 함수가 있고
  2. 더 빨라서!
    • push할 때 vecotr는 new 없이 미리 할당 받은 capacity 내에서 땡겨온다.
    • pop할 때는 capacity는 그대로 유지한 체 size만 줄어들고 pop한 원소를 배제한다. 즉 실사용 원소 개수는 줄이는 식.


🌜 개인 공부 기록용 블로그입니다. 오류나 틀린 부분이 있을 경우 
언제든지 댓글 혹은 메일로 지적해주시면 감사하겠습니다! 😄

맨 위로 이동하기

Cpp 카테고리 내 다른 글 보러가기

댓글 남기기