이번 포스팅에서는 동적 배열과 C++ vector에 대해 정리해 보려고 합니다.
동적 배열이란 동적 메모리 할당을 이용해 생성한 배열을 말합니다.
동적 메모리 할당(Dynamic memory allocation)이란?
프로그램 실행 중 필요한 크기의 메모리 공간을 할당하여 사용하는 기법을 말합니다. 동적으로 할당한 메모리는 사용이 끝나면 명시적으로 메모리를 해제해 줘야 합니다.
- C 언어에서는 malloc() 또는 calloc() 함수로 data를 메모리에 할당하고, free() 함수로 메모리에서 해제합니다.
- C++ 언어에서는 new 연산자로 data를 메모리에 할당하고, delete 연산자로 메모리에서 해제합니다.
- 동적 메모리 할당은 힙(heap) 메모리 영역을 사용하므로 대용량 배열도 할당해 사용할 수 있습니다.
#include <iostream>
int main()
{
// 배열 크기 입력
int sz;
cin >> sz;
// 동적 배열로 배열 포인터 초기화
int* arr = new int[sz] {};
// 동적 배열 원소 초기화
for (int i = 0; i < sz; i++) {
arr[i] = (i+1) * 10;
}
// 동적 배열 원소 출력
for (int i = 0; i < sz; i++) {
cout << arr[i] << " ";
}
// 동적 배열을 메모리에서 해제
delete [] arr;
return 0;
}
// Result
// 5
// 10 20 30 40 50
std::vector란?
C++에서 C 스타일 동적 배열을 대체하는 가변 크기 컨테이너입니다.
- 초기화 과정에 데이터의 크기를 지정하지 않아도 됩니다.
- 크기를 확장할 수 있습니다.
- 원소의 타입을 매개변수로 사용하는 클래스 템플릿이며, <vector>에 정의되어 있습니다.
#include <vector>
using namespace std;
int main()
{
// 1차원 vector 초기화 방법
vector<int> vec1; // empty vector
vector<int> vec2(10); // 0 0 0 0 0 0 0 0 0 0
vector<int> vec3(10, 1); // 1 1 1 1 1 1 1 1 1 1
vector<int> vec4 {10, 20, 30, 40, 50}; // 10 20 30 40 50
vector<int> vec5(vec4); // 10 20 30 40 50
vector<int> vec6(vec4.begin(), vec4.begin() + 3); // 10 20 30
}
#include <vector>
using namespace std;
int main()
{
// 2차원 vector 초기화 방법
vector<vector<int>> mat1(2, vector<int>(3, 1));
// 1 1 1
// 1 1 1
vector<vector<int>> mat2 {
{1, 2, 3},
{4, 5, 6}
};
// 1 2 3
// 4 5 6
}
operator[] : 특정 위치 원소의 참조를 반환합니다.
front() : 첫 번째 원소의 참조를 반환합니다.
back() : 마지막 원소의 참조를 반환합니다.
push_back() : 마지막에 원소를 추가합니다.
pop_back() : 마지막 원소를 삭제하며, 마지막 원소를 반환하지 않습니다.
insert() : 특정 위치에 원소를 삽입합니다.
erase() : 특정 위치의 원소를 삭제합니다.
clear() : 모든 원소를 삭제합니다.
size() : 원소의 개수를 반환합니다.
empty() : 비어있으면 true를 반환합니다.
emplace(), emplace_back()은 각각 insert(), push_back()과 동일한 기능을 수행하지만 동작 원리가 다릅니다.
#include <vector>
#include <string>
using namespace std;
int main()
{
vector<string> vec;
// push_back()은 임시 string을 생성해 "hello"를 임시 string에 복사한 뒤, 임시 string을 vector에 전달해 삽입합니다.
vec.push_back("hello");
}
#include <vector>
#include <string>
using namespace std;
int main()
{
vector<string> vec;
// emplace_back()은 임시 string을 생성하지 않고 vector 내부에서 "hello" 값을 갖는 string 객체를 생성한 뒤 vector에 삽입합니다.
vec.emplace_back("hello");
}
결론적으로 emplace(), emplace_back()을 사용하면 불필요한 임시 객체의 생성과 객체의 복사를 피할 수 있습니다. 따라서, 더 효율적인 코드를 작성할 수 있습니다.
emplace 함수를 사용하는 이유는 불필요한 임시 객체 생성과 객체 복사를 피하기 위함입니다. 따라서, emplace 함수 인자로 객체 생성을 위한 인자를 직접 전달해야 합니다.
#include <vector>
#include <string>
using namespace std;
int main()
{
// "hello"를 vec에 삽입하려는 경우
vector<string> vec;
// emplace_back()의 잘못된 사용법.
string str = "hello";
vec.emplace_back(str);
// emplace_back()의 올바른 사용법.
vec.emplace_back("hello");
}
이번에는 동적 배열과 vector에 대해 정리해 봤습니다.
emplace 함수에 대해 이해하는데 시간이 좀 걸렸네요.