감자였던 내가 이세계에선 개발자꿈나무?!

사실은 감자

ASSINGMENT/고급 C++

[과제] 6주차 과제 - 포인터, 동적 객체

이빨빠진 옥수수 2023. 4. 11. 01:58

일단 먼저 포인터에 대해 알아보겠댜

 

포인터란?

식별자를 통해 해당 변수가 저장된 메모리 위치에 접근하는 것 

* 를 이용하면 포인터를 생성하며, 여기다 특정 변수의 메모리를 저장해준다

&를 이용하면 변수가 저장된 메모리 위치에 접근하게 된다

 

또한 연산자를 통해 변수에서 변수, 메모리에서 메모리로 접근하는데

. 를 이용하면 변수끼리의 접근

-> 를 이용하면 포인터(메모리)끼리의 접근

이렇게 된다.

 

CStudent sungshin;
CStudent* p;
p=&sungshin;
sungshin.set_student("sungshin","2023","ISTJ");
cout<<p->get_name()<<":"<<p->get_mbti()<<endl;

위 코드는 포인터를 통해 멤버함수를 호출한 경우이다.

 

Q1. ' . ' 연산자를 사용하여 구현하는 방법은?

. 은 위에서 설명했듯 변수끼리의 접근이다 따라서 p는 포인터로 생성된 변수이므로

p가 아닌 sungshin을 통해 접근해야한다

sungshin.get_name(), sungshin.get_mbti() 이렇게 멤버 함수를 호출하면 된다

 

Q2. line 3,4 없이 바로 5를 실행하면 어떻게 될까요?

line 3,4 는 각각 포인터에 메모리 주소를 저장해주는 코드, 함수 호출하여 함수에 해당 변수를 지정해주는 코드이다.

그렇기에 저 두개의 라인이 사라지면 sungshin객체가 함수에 접근하지도 못하고 객체의 메모리주소도 저장해주지 못 한다.

그렇게 실행하게 되면 일단 p의 값을 모르기 때문에 그리고 그 값이 함수에 접근할 수 없기 때문에 에러가 날 것이다.

 

Q3. 모든 객체를 다음 값으로 만드세요.

"Sugeong", "2023", "ISTJ"

int main (){
CStudent sungshin;

sungshin.set_students("sungshin","2023","ISTJ");
CStudent Sugeong[3];
Sugeong[0].set_students("ABC","2021","ISTJ");
Sugeong[1].set_students("DEF","2022","ISTP");
Sugeong[2].set_students("GHI","2023","INFJ");
CStudent* p;
p=Sugeong;

for(int i=0;i<3;i++){
    Sugeong[i].set_students("SUGEONG","2023","ISTJ");
    cout<<p->get_name()<<endl;
}

}

Q4. 디버깅을 통해 temp_name1과 temp_name2가 같나 확인해 보세요

    string temp_name1, temp_name2;
    temp_name1=p[0].get_name();
    temp_name2=(*p).get_name();

둘 다 같다.

 

 

Q5. 아래 두 방식 중 어떤 연산자를 사용해야 할까요?

    for(int i=0;i<3;i++){
        cout<<(*p++).get_name()<<endl;
    }
    for(int i=0;i<3;i++){
        cout<<(p+i)->get_name()<<endl;
    }
    for(int i=0;i<3;i++){
        cout<<(Sugeong+i)->get_name()<<endl;
        cout<<(Sugeong+i).get_name()<<endl;
    }

8,9 번째 줄 중에서 하나는 포인터연산자 하나는 변수 연산자인데

sugeong은 p와 같은 포인터이므로 ->를 사용해야 한다.

 

Q6.

    int k;
    int* p=&k;
    delete p;

delete 연산자는 생성자~소멸자 사이에서 사용하는 연산자이다.

여기에서 포인터가 아닌 그냥 p에 대한 생성자가 없었기때문에 delete연산자는 생성되지 않은 변수를 지우려고 하기 때문에 에러가 난다.

 

Q7.

int *a =new int[3]
delete a;
int* b =new int;
delete[] b;

 

상단의 코드에서는 a라는 배열을 동적할당을 시켜 만들어줬지만 메모리 삭제 시 delete a라고 하면 a라는 를 할당하는 말이 되므로

배열에 할당된 메모리가 초기화가 되지 않는다.

 

또한 다음 동적 배열 생성시에는 동적배열을 얼마나 생성할 지 정해주지 않았기 때문에 에러가 난다.

 

 

Q8,9,10

p는 동적 배열의 이름이고 q는 포인터를 통해 p의 메모리에 접근하려 했으나, &연산자를 사용하지 않아서 메모리주소가 정상적으로 저장되지 않았다.

q는 배열p에 정상적으로 접근하지 않았기 때문에 q[0],q[1]은 아예 다른 것이다 (왼쪽에 static 이 아닌 local에 저장됨)

따라서 q[1]=2; 라인을 추가해줘도 배열에 정상적으로 저장되지 않는다.

 

Q11

set_student를 ->연산자로 받기 위해선 포인터에 해당하는 값이여야 하므로 arr를 포인터로 저장해줬다.

 

Q12. 메모리 누수가 어떻게 발생할까요?

int* p;
for (int i=0; i<999; ++i){
	p=new int[1000];
  }

p에 동적배열이 할당되는데 거의 1000번에 가깝게 메모리1000을 할당하는 메모리를 계속 할당해주게 되므로 메모리누수가 발생한다.

 

Q13, 14

func_changeMBTI는 C라는 객체에 새로운 mbti를 저장해뒀지만 set_student를 통해 메인 함수에서 호출된 객체의 값이 저장되었고 그 값은 저 함수만 가지곤 접근하여 바꿀 수 없기 때문이다.

 

Q15,16

func_changeMBTI는 입력값이 클래스 객체인데 이때 메모리 주소를 입력받는 것이 아니므로 에러가 뜬다.

 

Q17. arr+2, arr[2], ref, &ref 중 같은 것끼리 묶어보세요.

int& func_ref(int[]s, int idx){
	return s[idx];
   }
int main(){
	int arr[3] = {1,2,3};
    func_ref(arr,1)=5;
    int& ref=func_ref(arr,2);
    ref=9;
    reutrn 0;
}

(arr+2,&ref) (arr[2],ref)

 

Q18 위 코드는 왜 잘못되었을까요?

위 코드에서 함수는 인덱스의 값을 반환시키는데 두번쨰 함수를 선언 할 때에는 ref의 메모리값에 접근했으므로 잘못되었다.