C++

<C++> 6. 배열과 벡터

Parkjung2016 2024. 3. 26. 14:55

배열

  • 같은 종류의 데이터들이 순차적으로 메모리에 저장되는 자료 구조

배열요소 수

void main()
{
	int arr1[2];	// OK
    
    int N = 2;
    //int arr2[N];	// ?
    
    const int CN = 2;
    int arr3[CN];	// OK
}

배열 초기화

void main()
{
	int arr1[8] = {1};
    int arr2[8] = {1, };
    int arr3[8] = {0};
    int arr4[8] = {};
    int arr5[8] = {1, 2, 3};
    int arr6[8] = {1, 2, 3, };
    int arr7[8];
}

 

포인터로서의 배열명

#include <iostream>
using namespace std;

void main()
{
	int arr[2] = {1, 2};
    int*p = arr;
    cout << *p << ", " << *arr << endl;
}

배열명과 포인터의 차이

int main()

{

    char s[] = " C++ ";

    char* s2="C++";

}

s1의 이름 자체는 배열의 첫 요소를 가리키는 상수 포인터

s1에는 더이상 다른 값이 대입될 수 X

s2는 상수가 아닌 일반 포인터이므로

언제든지 다른 주소를 대입하면 다른 영역을 가리킬 수 있음

배열 인자

void func(int arg)
{
	arg++;
    cout << arg << endl;
}

void main()
{
	int a=1;
    func(a);
    cout << a << endl;
}

/*
func() : 2 출력
main() : 1 출력
*/

 

void func(int arg[1])
{
	arg[0]++;
    cout << arg[0] << endl;
}

void main()
{
	int arr[1]={1};
    func(arr);
    cout << arr[0] << endl;
}
/*
func() : 2 출력
main() : 1 출력
*/

2차원 배열

  • 배열 요소들이 2차원으로 나열된 배열

2차원 배열 초기화 및 출력

 

Fill()

  • 연속성을 뛴 자료구조(벡터나 배열 같은)의 시작점부터 연속된 범위를
    어떤 값이나 객체로 모두 지정하고 싶을 때 사용하는 변수

  • #include <algorithm>: fill함수를 사용하기 위해 필요한 헤더파일
  • first: 채우고자 하는 자료구조의 시작위치
  • iteratorlast: 채우고자 하는 자료구조의 끝위치 last는 포함하지 않음
  • val: first부터 last전까지 채우고자 하는 값

표준 템플릿 라이브러리(STL)

  • C++ 표준 라이브러리에는 다수의 클래스 템플릿과 함수 템플릿이 마련됨

컨테이너

컨테이너는 자료를 저장하는 창고와 같은 역할을 하는 구조이다.

즉 배열이나 연결 리스트, 벡터, 집합, 사전, 트리 등이 여기에 해당한다.

컨테이너의 분류

반복자

  • 컨테이너의 요소를 가리키는 데 사용된다. 일반화된 포인터(generalized pointer)
  • STL 알고리즘은 반복자를 통하여 컨테이너에 접근하여 작업한다.

반복자의 연산자

  • 배열의 단점을 보완한 컨테이너
  • 실행 시간에 크기를 변경할 수 있는 동적 배열
  • 추가되는 요소의 개수에 따라서 자동적으로 크기가 조절됨
  • 벡터  = 가변길이 배열
  • #include <vector>

벡터 선언

벡터 초기화

vector 동작 원리

  1. 여유분을 두고 메모리를 할당
  2. 여유분까지 꽉 찼으면,
    - 기존의 영역을 버리고 새로운 영역을 만든다.
    - 기존의 size에서 약 1.5배 사이즈로
  • v.capacity(); // 여우분을 포함한 총 용량 개수
  • v.size(); // 실제 사용하고 있는 데이터 개수
  • * capacity는 늘면 늘지, 줄어들지는 않는다. v.clear()을 해도 줄어들지 않음.

복사 비용을 줄이기

필요한 사이즈를 대략 알면 reserve() 또는 resize()를 사용하여 capacity를 설정
- v.reserve(10000) 하면 capacity가 10000으로 처음부터 잡힘, 사이즈는 변화하진 않음
- v.resize(1000) // capacity도 1000으로 강제 설정됨. 여기서 pushback 하면 1000번째 인
덱스부터 값이 들어감
- v.resize(n)크기를 n개로 변경한다. 커진 경우에는 빈 곳을 0으로 초기화한다.
- v.resize(n, m)크기를 n개로 변경한다. 커진 경우에는 빈 곳을 m으로 초기화한다.

 

벡터 클래스 멤버함수

push_back(데이터) 벡터 끝 부분에 데이터 추가
pop_back() 벡터 끝 부분에서 데이터를 삭제
front() 벡터 맨 앞에 값 반환
back() 벡터 맨 뒤에 값 반환
insert(반복자, 데이터) 반복자 위치 앞에 데이터 삽입
ease(주소)
erase(주소1, 주소2)
주소 위치 데이터만 삭제
주소1에서 주소2앞까지 데이터 삭제
empty() 벡터 안에 데이터 존재 안하면 true리턴
size() 벡터 안 데이터의 개수를 리턴
at(index)
벡터 객체이름[index]
벡터의 원소를 참조
clear() 벡터의 원소를 모두 제거

 

벡터와 연산자

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

int main(void)
{
	vector<int> v1{1,2,3,4,5};
    vector<int> v2(v1);
    
    if(v1==v2)
    {
    	cout << "2개의 벡터가 일치합니다. " << endl;
    }
    return 0;
}

반복자(iterator)

벡터와 달리 다른 컨테이너는 v[i]와 같이 인덱스 접근이 안될 수도 있음

모든 컨테이너에 공통적으로 접근할 수 있는 방법

v.begin()는 반복자만 쓸 수 있음

begin() 벡터의 첫 iterator(=첫 원소의 주소)를 리턴
end() 벡터의 끝 iterator(=마지막 원소 다음 주소)를 리턴

반복자를 사용하는 다양한 방식

2차원 벡터

  • 배열 요소들이 2차원으로 나열된 배열