본문 바로가기
공부

22.11.09 복습

by MY블로그 2022. 11. 9.

vector = 배열과같다 > 동적 할당이 가능한 배열 이라고 본다.

vector<int>vec; 를 동적 할당 하려면 일반 int는 불가능하지만 포인터를 사용하면가능하다.

*vec.push_back(new int(3)); -> 포인터 형식으로 새로운 동적할당 적용
cout << *vec[0] << endl; -> 출력하면 포인터이기때문에 3의 주소가 나온다.
delete[] vec[0]; -> 할당후에 벡터여도 포인터사용하였으면 포인터는 직접 해제해줘야한다.

 

벡터는 자동적으로 할당이 해제 되지만 포인터를 사용하여 new를 사용하였으면

delete 를 사용하여 해제를 꼭 해줘야 한다.

 

추가적인 정보 >

vec.push_back(); 과 동일하게 사용할수있는것은 vec.emplace_back(); 이 있다.

push => 밀어넣다 / back => 뒤에.

emplace => 설치하다 / back => 뒤에.

현재는 비슷하다는것만 알고있어두자. 정확한 사양은 다르다.

지금은 push_back(); 만 정확하게 사용하도록 하자.

추가

push emplace 비교 

https://m.blog.naver.com/enter_maintanance/221829474489

 

[C++] 생성자 (복사 생성자, 이동 생성자, Push_back, emplace_back)

# 생성자 - Class를 통해 객체를 생성하려면 생성자를 거쳐야 하고 제거하려면 소멸자를 거쳐야 합니다. ...

blog.naver.com

 

벡터는 뒤에서만 동적할당하여 새로운 공간을 붙여줄수 있다.

앞에서 값을 넣는순가 넣은지점부터 뒷부분이 전부 밀려나는 현상이 발생한다.

벡터는 힙공간에서 내부를 이동하며 공간을 자동적으로 할당하고있기때문에

처음삽입 중간삽입 중간삭제등등 끝부분이아닌곳의 수정은 매우 불리하다.

 

Tip . 코드위에 커서를 올리면 반환형, 매개변수 등을 볼수있다.

아래의 insert 사진을 예로들자면

이터레이터가 나오고 뒤에 값을 넣어라라는 것이 나오며

변수명에 where 이 나온다. 어디에 삽입할지를 묻는 것이다.

erase도 비슷하다. 어디를 지울지 묻는것이다.

 

insert 안의 begin은 반환값이 이터레이터이고 함수 이름이 표시된다.

 

공통 적으로 나오는 iterator 이터레이터 는 반복자 이다.

이터레이터는 포인터 처럼 사용된다. 몇번째 인지를 가리키는 용도로 쓴다.

for (vector<int>::iterator i = vec.begin(); i != vec.end(); i++)
    {
        cout << *i << endl;
    }

이터레이터 사용 방식.... 어렵다. 위에 코드를 올려보면 형식이 보이긴 한다.

 

begin 그리고 end 에 대하여. (iterator 형이다)

begin은 시작점이고 end는 끝지점 +1 이다.

끝지점+1인 이유는  만약 배열의 안쪽에 무엇인가를 찾고자할때 찾는 내용이 안에없으면

없다는것을 반환해 줘야하는데 그 반환값이 끝지점+1 부분에있다.

0 1 2 3 4 end+1

위으 표를 예시로모자면 여기서 3을 찾고자하면 0번째부터 반복하여 하나씩 찾기시작하고

3을찾으면 3을 반환해준다.

그리고 01234 외의 것을 를 찾고자 한다면 없기 때문에 end+1를 반환해준다.

(이부분은 알아두면 vector 뿐만아닌 다른 STL의 공부에 도움이 될 수 있다.)

배열은 연속적인 장점을 가지는 반면

크기가 고정적이며 탐색에 불리하다 > 끝에있는 것을 찾기위해서는 배열만큼의 탐색이

진행되기때문에 배열이 크면클수록 부담이 된다.

중간부분에 삽입하면 하나씩 뒤로 밀려나고 중간부분을 삭제하면 그만큼 당겨진다.

왜냐하면 배열은 연속적인 구조이기때문에 빈공간이 허락되지 않는다.

 

front & back = 참조 리턴 이다 (중요)

위의 사진을 보면 front의 코드 위에 커서를 올렸을때 보여지는 부분이다.

오늘 예시는 전부 int형의 vector를 사용하고 있다.

중요한것은 인트 옆의 참조형(&) 이다. 

front 는 시작부분 참조리턴

back 은 마지막부분 참조리턴

참조형(&) 이라는 것은 값을 단순히 복사해오는 것이아니라 참조를 하기때문에 

주소를 그대로 받고 있다는 것이다. 때문에 참조는 주소를 공유하고 있는 특성으로

해당 주소에 직접 접근하기때문에 수정이 가능하다는 것이다. (iterator 이터레이터 형은 불가능)

 

size 는 배열의 크기 컨테이너 라고 부른다. (컨테이너 크기 반환)

resize 는 배열의 사이즈를 재조정 한다. (컨테이너 크기 조정)

reserve 는 내부버퍼 크기 조정을 한다. (여유공간)

capacity 는 내부버퍼 크기를 볼수 있다.

 

clear 는 배열을 비워준다 (컨테이너 비우기) 

shrink_to_fit 는 내부버퍼를 비워주는 것이다.

위는 clear / shrink_to_fit 의 사용 예제이다.

erase만 사용했을때에는 배열은 사라지지만 내부 버퍼는 그대로 이다.

clear를 사용하면 사이즈는 초기화(제거)되지만 내부버퍼는 그대로이기때문에

shrink_to_fit을 사용하여 내부버퍼도 같이 제거해준다.

clear & shrink_to_fit 은 두개를 같이 쓰인다.

 

 

*** 중요***

당일 수업 후반부에 예시로본 벡터를 이용한 카드배열 만들기에서

더보기

당일 수업의 vector 를 이용한 카드 구조체 생성 코드 참고자료. 

#include <iostream>
#include <vector>
#include <string>

using namespace std; 

struct Card 
{
    int num;
    string shape;

    void Print()
    {
        cout << shape << num << endl; 
    }
};

Card MakeCard(int n, string str)
{
    Card temp;
    temp.num = n;
    temp.shape = str;

    return temp;
}

int main()
{
    vector<Card> deck;

    //임시변수를 이용한 방법
    Card temp;
    temp.num = 10;
    temp.shape = "♧";

    deck.push_back(temp);

    //함수를 이용한 방법
    deck.push_back(MakeCard(5, "♧"));
    deck.push_back(MakeCard(7, "♧"));
    deck.push_back(MakeCard(2, "♧"));

    for (int i = 0; i < deck.size(); i++)
    {
        deck[i].Print();
    }

    deck.erase(deck.begin() + 2);

    deck.clear();
    cout << "사이즈 : " << deck.size() << endl;
    cout << "내부버퍼 : " << deck.capacity() << endl;

    deck.shrink_to_fit();
    cout << "사이즈 : " << deck.size() << endl;
    cout << "내부버퍼 : " << deck.capacity() << endl;

    return 0;
}

벡터는 멤버함수를 가질수 있고 출력 함수를 만들수가 있다.

멤버함수는 구조체 안에 있고 구조체 라는 것은 카드의 한장한장을 나타내는것이고

한마디로 구조체 라는 것을 각각 다 가지고 있다.

프린트 함수를 만들었을때 출력되는것은 덱의 몇번째라는 값을 다 가지고있으니

이미 가지고 있는 것들을 출력 시키는 것이다. (어려운 개념이다 ....)

이는 곳 출력시 덱의 몇번째를 지정해줄 필요없다는 것이다.

이것을 객체 지향 이라고 한다.

자신이 누구이며 무엇을 가지고 있는지가 주가 되어 자신을 출력 시키는 것이다.

현재 우리가 프로그래밍을 하면서 순서대로필요한 것들을 입력 시키는 것은 절차지향이라한다.

C 언어는 절차 지향 이다.

우리가 C++을 사용하는 이유중하나는 객체지향을 사용하기 위해서 이다.

이것은 게임 개발에서 떨어뜨릴수 없는 기능이다.

 

ex)게임내에서 플레이어 몬스터 보스 등등 다양한 것들은 객체로 보며

각각은 구조체로 만들어진다. HP, DAMGE, 등등등...

각각의 정보를 만들고 출력시켜주며 관리하는것은 객체지향으로 이루어 진다.

각각 개별을 관리하기가 수월하기때문에 뺄수가 없는 기능이다.

누구인지 먼저 알고 접근을 하기 떄문에 그대로 출력이 가능하다는 것이다.

 

객체지향은 앞으로 심화 수업이 이루어질 예정이다. 

 

* 지속적으로 복습을 해야 될것 같다.. 앞으로의 수업에서 벡터는 깊이 들어가지 않은채 진도가 계속 나가기때문에

벡터는 복습하고 지속적으로 사용하면서 익숙해 져야 한다.

댓글