CPP_어소_54_클래스를 이용한 배열

CJB_ny·2022년 6월 30일
0

CPP_AROTHO

목록 보기
53/83
post-thumbnail

클래스

3~6까지 이니셜라이저 사용해서 초기화를 해주도록 한다.

동적 할당 malloc대신 -> new 키워드

우리가 C스타일 이였다면

malloc을 통해서 했는데

동적 할당 방식이 "new" 라는 키워드가 생김

해제 free -> delete

소멸자가 호출되는 상황에서 뭐가를 셋팅해주어야함.

int* p 일 경우는 그냥 delete p해주면된다.

그런데 int가 여러 묶음으로 있을 경우에는

고런 경우에는 delete[] 이렇게 해주면된다. ( 배열 형태의 메모리 지울 때 )

new, delete 이해하기

malloc은 그냥 메모리 공간만 만들어서 던저주고 거기를 어떻게 해석하느냐에 따라서 -> 사용한다.

순수하게 size만 요청 => 사용자가 마음대로 가능.

예시

A라는 클래스가 50바이트인데 힙 메모리에 이 클래스 객체 하나를 사용하려고 동적할당을 할 것이다.

그러면 클래스니까 생성자에 명시된 대로 클래스를 초기화 한다.

C에서는 malloc으로 만들어주고 포인터로 이곳을 가르켯는데

클래스에서는 생성자 라는게 생겨서 초기화 해주는 보장을 해주어야한다.

그래서 동적할당 할 경우 그곳을 어떻게 볼 것인지 (해석) 할 것인지 명시를 해주어야함.

클래스를 동적할당 ❗

CTest만큼을 동적할당 하려면

CTest* pTest = new CTest();

여기서 이제 new 라는게 뭘 하는거냐?

=> malloc을 할 것이다. 그리고 CTest라고 자료형을 알려줬고,

그곳에 CTest객체가 들어 올 것이고 CTest에 생성자까지 호출해주고

=> a = 10이라고 초기화 까지 해주고 그곳의 주소를 pTest한테 줄 것이다.


스스로 정리 ❗ 👍

Test* test = new Test();

는 new키워드 사용 -> 동적할당 -> 자료형을 Test()라고 명시

동적할당한 주소룰 Test포인터로 test라는 변수명으로 받는다.

test에는 new Test()를 한 주소가 들어가있고

OS에 따라 크기가 가변적인 포인터 변수로 받기 때문에 현재 64비트가 8바이트의 size가 나온다.

Test t1;

이녀석은 Test클래스의 객체를 t1이라는 이름으로 받았고,

Test의 멤버 변수로는 int, int, float => 12바이트 만큼의 메모리 공간이 필요하다.

main함수가 호출되면서 t1이라는 애도 "스택"안의 main함수 안에 12바이트 만큼 차지를 하게 되는 것이다.


다시 delete

pTest의 객체의 타입이 CTest포인터 였기 때문에

delete가 pTest라는 주소를 받아갈 때,

CTest* 라는 타입값을 확인을 해서 그냥 포인터가 아니라

CTest를 가르키기로 한 포인터였다는 것을 알아가는 것이다.

new CTest해서 새로운 객체 만들었는데 그곳의 주소를 CTest* pTest로 받아 간 것이다.

그리고 객체를 통해서 멤버함수를 호출 한다고 했다❗

호출된 생성자에는 new CTest를 한 객체가 있고, 그 객체의 주소를 pTest가 가지고 있는 상황.

delete pTest를 하면 그 주소에 해당하는 객체에 접근을 해서 소멸자 호출함.

그래서 아까 내가 스스로 정리 한 부분에서!!!

Test* test = new Test(); 해서 주소를 받아갔지만

test.PrintTest()호출이 가능했던 것이다.


비용 👍

Test* test = new Test(); 이거랑 Test t1;

이거는 차이가 뭐냐하면은? => 비용이다.

Test라는 클래스가 크기가 ㅈㄴ 크다고 가정.

그러면 Test t1을 존나큰 객체를 하나 만드는 것이고ㅓ

Test* test = new Test(); 얘는 만들기는 하지만 참조만 계속 하는것이다.

(이부분 조금 애매함)


클래스 가변배열

PushBack 함수

ReSize

뭐 이렇게 바뀔 것이다. (this는 없애도 무방함)

실습

원래는 48~50까지 였었는데 -> 구조체를 사용할 경우

클래스를 사용하면 이렇게 바뀐다.

carr[1] 연산을 하고싶다 -> 오버로딩

클래스한테 특정 연산자 호출 되었을 때,

할 수 있었던거 -> 함수오버로딩을 통한 기능 구현

ㄴㄴ => 연산자 오버로딩 정의가능.

연산자 오버로딩 ❗

진짜 배열처럼 사용하기 위하여

왜냐하면 지금 carr[1]이것은 말이 안되는 문법임. carr은 객체인데

먼 주소연산??

반환타입이랑 안내 내용조금 수정해야한다.

이런식으로 수정익 가능하고 이렇게 사용가능.

굿.

함수의 반환 타입 ❗❗❗ 무조건 읽으셈

이거 안되는 이유는

함수의 반환타입은

호출한 쪽이 A(밑) 호출당한 함수 B(위) 라고 했을 때, 반환을 하면 호출당한 함수에서

B함수가 종료가 되면서 반환된 값이 임시적으로 저장되어 있는 곳에서(레지스터에서)

"꺼내온다"

값을 임시 바구니에 넣고 꺼내온다.

crr[i] = 200; 이게 원하는 바는 무엇이냐 하면은

arr의 pInt 의 인덱스에 접근을 해서 (1번쨰 인덱스)에 접근을 해서 거기에 200을 넣어주려고 하는 것이다.

지금 하려는 것은 1번인덱스에 있는 값을 꺼내와서 임시 바구니에 넣고

그 임시 바구니에 200을 넣는 꼴이다.

임시바구니에 넣어도 아무 소용없음.

내가 원하는 곳을 수정할 수 없다.
원본 그자체가 아니다.

원본 그 자체에 접근할 수 있는 방법 2가지

    1. 해당변수의 주소

함수의 반환형을 int* 로 바꾸고

return &this->m_pInt[idx] 이렇게 하거나

"주소연산"이기 떄문에

원본으로 접근을 하는 '*' 없애고 return (m_pInt + idx) 해도가능.

이렇게 로 원본 값에 접근을 해서 (carr[1] = 100) 해서 가능함.

그런데 원래 배열의 문법과는 아무 관련이 없다.

이모양 ❗

이런 모양이 만들어 질려면 C++추가된 Reference를 사용해야한다.

그래서 operator함수가 반환되는 곳이 곳을

그대로 "참조"로 전달을 한다.

pInt의 indexNum의 공간을 참조로 반환을 하면 그 인덱스번호의 주소를 전달한 것이기 때문에

carr[1] = 100;하면 원본(주소)에 접근을 해서 값 수정이 가능하다.

profile
공부 일기장으로 변해버린 블로그 (https://cjbworld.tistory.com/ <- 이사중)

1개의 댓글

comment-user-thumbnail
2022년 7월 2일

비용 부분 조금 이해가 조금 안가는게 Test t, Test t2... 이렇게 만들때랑 Test* t = new Test 하나존재할때 를 말하는거같다.

답글 달기