본문 바로가기
[C++ ] 자료구조

Part2. 배열 : C 언어에서 C++ 언어로

by 말하는 감자 처음 보세요? 2023. 4. 3.

[01. C 스타일 배열과 std::array]

① 배열(array)이란?

    ✔︎ 같은 종류의 데이터가 연속적으로 저장되어 있는 자료 구조

          - 

다섯 학생의 점수를 저장하려면?

                int score 1, score 2, score 3, score 4, score 5;

                         --> int scores[5];

               (인덱스: 0 기반, zero-based)

               (윗 배열은 한 배열당 4byte이니 4byte*5=20byte이다)

배열의 시각화

          - 인덱스(index)를 사용하여 원하는 원소(element)에 곧바로 접근 가능: O(1)

          - 캐시 지역성 (cache locality)                  ㄴ 배열의 각 원소는 서로 인접해 있기 때문에 하나의 원소에 접근할 때 그 근방에 있는 원소도 함께 캐시(cache)로 가져옴

          - 반복문에서 배열을 사용하면 효율적인 프로그래밍 가능

          - 상수/상수표현식으로 크기를 지정(크기 불변)

          - 스택 메모리 영역에 할당 ➡︎ 보통 1MB 할당(이보다 더 큰 배열을 할당 시 오버플로우)

 

② C 스타일 배열 

▶︎ C 스타일 배열 예제 코드 

#include <iostream>
using namespace std;
int main()
{
    int scores[5] = {50, 60, 70, 80, 90};
int sz = sizeof(scores) / sizeof(scores[0]); // int sz = size(scores);
int s = 0;
for (int i = 0; i < sz; i++) {
        s += scores[i];
}
float m = (float)s / sz;
cout << "Mean score: " << m << endl;
}
Mean score: 70

C스타일 2차원 행렬

③ std::array이란?

    ✔︎ C++에서 C 스타일 배열을 대체하는 고정 크기 컨테이너 (C++11)

          - 원소의 타입과 배열 크기를 매개변수로 사용하는 클래스 템플릿

          - <array> 헤더 파일에 정의되어 있음

          - C 스타일 배열처럼 사용할 수 있는 [] 연산자 오버로딩을 제공

          - 대입 연산자 지원 (깊은 복사)

          - 배열 크기를 정확하게 알 수 있음, array::size()

          - 반복자 지원

template<class T, std::size_t N>   //T는 데이터 타입, N은 원소의 갯수
struct array;

▶︎ std::array 예제 코드

#include <array>
#include <iostream>
using namespace std;
int main()
{
    array<int, 5> scores = {50, 60, 70, 80, 90};
    int s = 0;
    for (int i = 0; i < scores.size(); i++) {
        s += scores[i];
    }
float m = (float)s / scores.size(); cout << "Mean score: " << m << endl;
}

          - std::array의 단점

                ㄴ 배열의 크기를 명시적으로 지정해야 함

                ㄴ 항상 스택 메모리를 사용

                ㄴ 고정 크기 배열이 아닌 가변 크기 배열을 더 선호함

                ㄴ 그러므로, std::vector라는 것이 더 많이 활용된다


[02. 동적 배열과 std::vector]

① 동적 메모리 할당(dynamic memory allocation)이란?

    ✔︎ 프로그램 실행 중 필요한 크기의 메모리 공간을 할당하여 사용하는 기법

       (이 때 필요한 크기라는 것은 동작할 때마다 고정된 것이 아니라 실행할 때마다 가변적인 크기)

       (ex. 동영상 편집 > 작은 크기 영상, 큰 크기 영상 이들은 동적으로 메모리 할당)

          - 동적으로 할당한 메모리는 사용이 끝나면 명시적으로 (할당된) 메모리를 해제해야 함

          - C 언어 : malloc() 또는 calloc() 함수로 메모리 할당하고, free() 함수로 메모리 해제

          - C++ 언어: new 연산자로 메모리 할당하고, delete 연산자로 메모리 해제 (보통 그냥 이거 써라,, 응응,,)

 

② 동적 메모리 할당을 이용한 동적 배열 생성 및 해제

    ✔︎ new[] 연산자를 이용하여 동적 배열을 위한 메모리를 할당하고, delete[] 연산자를 이용하여 동적 배열 메모리를 해제!

          - 동적 메모리 할당은 힙(heap) 메모리 영역을 사용하므로 대용량 배열도 할당 가능

int* ptr = new int[3];
// ptr을 배열처럼 사용. (e.g.) ptr[0], ptr[1], ptr[2] 
delete [] ptr;

이렇게 생긴다는 말이지..

▶︎ 동적 배열 예제 코드

#include <iostream>
int main()
{
int n;
    std::cin >> n;
// 동적 배열 할당 및 초기화 int* ptr = new int[n] {}; ptr[0] = 10;
ptr[1] = 20;
// ptr을 배열처럼 사용
for (int i = 0; i < n; i++) {
        std::cout << ptr[i] << std::endl;
    }
// 동적 배열 해제
    delete [] ptr;
}

▶︎ 메모리를 자동으로 해제하는 동적 배열 클래스

class DynamicArray
{
private:
    unsigned int sz;
    int* arr;
public:
    DynamicArray(int n) : sz(n) {
        arr = new int[sz] {};
    }
    ~DynamicArray() { delete [] arr; }
    unsigned int size() { return sz; }
int& operator[] (const int i) { return arr[i]; }
const int& operator[] (const int i) const { return arr[i]; }
};

int main()
{
DynamicArray da(5);
da[0] = 10;
da[1] = 20;
da[2] = 30;
for (int i = 0; i < da.size(); i++)
    cout << da[i] << ", ";
cout << endl;
}

➜ DynamicArray 생성자 앞에 있는 explicit 키워드는 묵시적 형변환(implicit type conversion)을 방지하기 위한 키워드로서 생략가능

 

③ std::vector이란?

    ✔︎ C++에서 C 스타일 배열을 대체하는 가변 크기 컨테이너

                ㄴ 초기화 과정에 데이터 크기를 지정하지 않아도 됨

                ㄴ 배열의 크기를 활장할 수 있음

          - 원소의 타입을 매개변수로 사용하는 클래스 템플릿

          - <vector>에 정의되어 있음

template<
    class T,
    class Allocator = std::allocator<T>  //내부에서 동적 메모리 할당을 사용자가 지정할 수 있는데 이는 기본 코드
> class vector;

 


[03. std::vector 사용법과 동작 방식]

① std::vector 객체 생성과 원소 참조

#include <iostream>
#include <vector>
using namespace std;
int main()
{
// 벡터 생성 vector<int> vector<int> vector<int> vector<int>
vector<int> v1; // int 값을 저장할 비어 있는 벡터 생성
vector<int> v2(10); // int 값 10개를 저장할 벡터 생성하고 0으로 초기화
vector<int> v3(10, 1); // int 값 10개를 저장할 벡터 생성하고 1로 초기화
vector<int> v4 {10, 20, 30, 40, 50}; // 유니폼 초기화(uniform initialization)
vector<int> v5(v4); // v4를 복사하여 v5 생성
vector<int> v6(v4.begin(), v4.begin() + 3); // v4의 처음 3개 원소를 이용하여 v6 생성
// 벡터 원소 참조

for (int i = 0; i < v6.size(); i++)
    cout << v6[i] << endl;

 

std::vector를 이용한 2차원 벡터 생성과 원소 참조

#include <iostream>
#include <vector>
using namespace std;
int main()
{
// 벡터 생성 vector<int> vector<int> vector<int> vector<int>
vector<int> v1; // int 값을 저장할 비어 있는 벡터 생성
vector<int> v2(10); // int 값 10개를 저장할 벡터 생성하고 0으로 초기화
vector<int> v3(10, 1); // int 값 10개를 저장할 벡터 생성하고 1로 초기화
vector<int> v4 {10, 20, 30, 40, 50}; // 유니폼 초기화(uniform initialization)
vector<int> v5(v4); // v4를 복사하여 v5 생성
vector<int> v6(v4.begin(), v4.begin() + 3); // v4의 처음 3개 원소를 이용하여 v6 생성
// 벡터 원소 참조

for (int i = 0; i < v6.size(); i++)
    cout << v6[i] << endl;
    
// 정수형 2차원 배열. 2행 3열. 0으로 초기화. 
vector<vector<int>> mat1(2, vector<int>(3, 0));

// 유니폼 초기화
vector<vector<int>> mat2 {{1, 2, 3}, {4, 5, 6}};

// 2차원 벡터 출력
for (int r = 0; r < mat2.size(); r++) {
for (int c = 0; c < mat2[r].size(); c++) {
cout << mat2[r][c] << " "; }
        cout << endl;
    }
}

③ std::vector 주요 멤버 함수와 기능

주요 멤버 함수 & 기능

    ✔︎ 자세한 동작 방식은 SKIP!

 

▶︎ std::vector 사용 예제

int main()
{
    vector<int> vec1 {1, 2, 3, 4};
    cout << vec1.capacity() << ":"<< vec1.size() << endl;
    
    vec1.push_back(5);
    cout << vec1.capacity() << ":"<< vec1.size() << endl;
    
    vec1.push_back(6);
    cout << vec1.capacity() << ":"<< vec1.size() << endl;
    
    vec1.insert(vec1.begin(), 0);
    cout << vec1.capacity() << ":"<< vec1.size() << endl;
    
    vec1.erase(vec1.begin() + 1, vec1.begin() + 3);
    cout << vec1.capacity() << ":"<< vec1.size() << endl;
    
    for (int i = 0; i < vec1.size(); i++)
        cout << vec1[i] << ", ";
}

출처: 어서와! 자료구조와 알고리즘은 처음이지? C++

'[C++ ] 자료구조' 카테고리의 다른 글

Part5. 큐  (0) 2023.05.15
Part4. 스택  (0) 2023.05.08
Part3. 연결 리스트  (0) 2023.04.11
Part1. 자료구조와 알고리즘은 처음이지?  (0) 2023.03.28

댓글