도대체 Vector 가 뭐길래!

정혜창·2024년 12월 27일

독학

목록 보기
15/28
post-thumbnail

코드카타를 진행해보니깐 vector을 배우지 않고서는 못배길것 같아서 이렇게 공부하게 되었다. 원래는 다음주 수강내용에 vector 수업이 있지만 아무렴 어때 예습하고 좋은거지 뭐. 코딩테스트가 너무 재미있는걸. 자 시작해보자

1. vector의 기본 개념

vector은 단어 자체가 일단 낮설진 않다. 중, 고등학교때 방향과 크기를 가지는 물리량으로 많이 접해보았기 때문일까? 그럼 C++에서 vector은 무엇을 의미할까. 사전적 의미로는 vector는 C++ 동적 배열을 관리하는 C++에서 제공하는 표준 라이브러리 클래스이다. vector는 배열처럼 데이터를 저장하지만, 크기가 동적으로 변경될 수 있기 때문에 유용하다. 즉, 원소가 추가되거나 삭제될 때 자동으로 크키가 늘어나거나 줄어든다.

  • 동적 크기 :

    vector는 원소를 동적으로 추가하거나 제거할 수 있기 때문에, 크기가 고정된 배열보다 더 유연하게 사용할 수 있다.
  • 동적 메모리 관리 :

    내부적으로 vector는 배열을 사용하여 데이터를 저장하지만, 크기를 자동으로 조절할 수 있다. 또한 메모리 할당이나 해제를 자동으로 관리해준다.

2. vector 사용 방법

먼저, vector를 사용하기 위해선 <vector> 헤더 파일을 포함시켜야 한다.

#include <vector>

그 후, vector는 클래스이므로, 객체를 선언할 때 데이터 타입을 지정해야 한다.

vector<int> v;		// 정수형 데이터를 저장하는 벡터
vector<string> v2;	// 문자열 데이터를 저장하는 벡터

3. vector의 주요 함수들

1. 초기화 및 원소 추가

  • push_back() : 벡터의 마지막 부분에 새 원소를 추가한다.
vector<int> v;		// 정수형 데이터를 저장하는 '빈' 벡터 선언
v.push_back(10);	// 벡터에 10 추가
v.push_back(20);	// 벡터에 20 추가
v.push_back(30);	// 벡터에 30 추가

for (int i : v){
	cout << i << " ";
}

2. 벡터 크기 확인

  • size() : 벡터의 원소 개수를 반환한다.
vector<int> v = {1, 2, 3, 4};
cout << v.size(); // 4 (벡터의 크기)

3. 원소 접근하기

  • 인덱스를 사용한 접근 : 벡터는 배열처럼 인덱스를 사용하여 원소에 접근할 수 있다.
vector<int> v = {1, 2, 3, 4}
cout << v[2]; // 3 (벡터의 2번 인덱스 값)
  • at() 함수 : 범위를 체크하여 안전하게 원하는 원소에 접근할 수 있다. 인덱스 범위 밖의 접근을 시도하면 out_of_range 예외가 발생한다.
cout << v.at(1); // 2 (벡터의 1번 인덱스 값)

4. 원소 삭제

  • pop_back() : 벡터의 마지막 원소를 제거한다.
v.pop_back();		// 벡터의 마지막 원소 제거 {1, 2, 3}
cout << v.size();	// 3 (벡터의 크기)

5. 벡터 초기화 및 복사

  • clear() : 벡터의 모든 원소를 제거하고 빈 벡터로 만든다.
v.clear()
cout << v.size();	// 0 (벡터가 비어있음)
  • 벡터 복사 : 벡터를 다른 벡터에 복사하면, 깊은 복사가 이루어져 원본 벡터와 복사된 벡터가 독립적인 객체로 존재한다.
vector<int> v2 = v; // 벡터 복사

6. 원소 수정

  • 인덱스를 사용하여 수정 : 벡터의 특정 원소를 수정할 수 있다.
v[0] = 100;		// 벡터의 첫 번째 원소를 100으로 수정
cout << v[0];	// 100

그 외 vector 클래스의 멤버 함수는 매우 많다. 자주 쓰는 기능은 외우고 필요한 기능이 있을 때 마다 참고 하는것이 좋을 것 같다.

참고 자료 : https://hwan-shell.tistory.com/119 (C++ vector사용법 및 설명 (장&단점))


4. 예제 코드

#include <iostream>
#include <vector>
using namespace std;

int main() {
	vector<int> v; //정수형 벡터 선언

	// 벡터에 원소 추가
	v.push_back(10);
	v.push_back(20);
	v.push_back(30);

	cout << v[0] << endl;// 10

	// 벡터의 크기 출력
	cout << "Size : " << v.size() << endl;

	// 벡터의 첫 번째 원소 접근
	cout << "First element : " << v[0] << endl;

	// 벡터의 원소 수정
	v[1] = 50;
	cout << "Second element after modification : " << v[1] << endl;

	// 마지막 원소 삭제
	v.pop_back();
	cout << "Size after popback : " << v.size() << endl;

	for (int i : v) {
		cout << i << " ";
	}

	return 0;
}


Dynamic Array 와 뭐가 다를까

출력은 위의 그림과 같이 나온다. 이렇게 벡터는 매우 좋아보이는게 사실이지만 단점도 존재한다. 우선 벡터의 맨 앞에 원소를 삽입하거나 삭제를 할 때는, 기존의 원소들을 이동시켜야 하기 때문에 효율이 떨어질 수 있고, 메모리를 동적으로 늘리거나 줄이기 때문에 메모리 사용이 일정 하지 않을 수 있다.

그런데 여기서 의문. 우리는 동적 배열이라는 것도 배웠는데 도대체 vector 와는 어떻게 다른 걸까

둘다 크기가 가변적인 배열처럼 동작하지만, 구현 방식이나 사용 편의성에서 몇 가지 중요한 차이가 있다.

1. 동적 배열(Dynamic Array)

동적 배열은 크기가 고정된 배열을 동적으로 확장하는 방식으로 구현된다. 즉, 초기 크기는 지정 되지만, 배열의 크기를 변경할 필요가 있을 때, 메모리 재할당을 통해 크기를 늘리거나 줄일 수 있다.

동적 배열의 특징

  • 수동 메모리 관리 : 동적 배열은 메모리 할당 및 해제를 프로그래머가 직접 관리해야 한다. 예를 들어, new[]를 사용해 메모리를 할당하고, delete[]를 사용해 해제한다.
  • 크기 변경 : 크기를 변경할 때마다 새로운 메모리를 할당하고, 기존 배열의 데이터를 새로운 배열로 복사해야 한다.
  • 배열의 크기 : 동적 배열의 크기는 고정되는 것은 아니지만, 크기가 변경될 때마다 새로운 메모리를 할당 해줘야 하므로 vector 보다 코드가 복잡해지고 오류가 발생할 확률이 높다.

동적 배열 예시

#include <iostream>
using namespace std;

int main() {
	
	int n = 5;
	int* arr = new int[n]; // 동적 배열 할당

	// 배열에 값 저장
	for (int i = 0; i < n; i++) {
		arr[i] = i * 2;
	}

	// 배열 출력
	for (int i = 0; i < n; i++) {
		cout << arr[i] << " ";
	}

	cout << endl;

	// 배열 크기 변경 (새로운 배열 할당)
	
	n = 10;					 // size 를 10으로 늘리겠다는 의미
	int* newArr = new int[n];

	for (int i = 0; i < 5; i++) {
		newArr[i] = arr[i];		// 이전 배열의 값 복사
	}

	delete[] arr; // 이전 동적 배열 메모리 해제

	// 새로운 배열 출력
	for (int i = 0; i < n; i++) {
		cout << newArr[i] << " ";
	}
	
	cout << endl;

	delete[] newArr; //새로운 배열 메모리 해제

	return 0;
}

profile
Unreal 1기

0개의 댓글