CH05 함수와 참조, 복사 생성자

jiyoon·2024년 4월 18일
0

함수의 인자 전달 방식 리뷰




함수 호출시 객체 전달




객체 치환 및 객체 리턴




참조와 함수

참조 '&' 란, 이미 선언된 변수에 대한 별명(alias)으로, 선언 시 반드시 원본 변수로 초기화하여야 한다.

  • 참조 변수
  • 참조에 의한 호출
  • 함수의 참조 리턴

참조 변수

int n=2;			Circle circle;
int &refn = n;		Circle &refc = circle;

참조 변수가 선언되면, 참조 변수 이름만 생성되며, 별도의 공간이 할당되지 않고 원본 변수의 공간을 공유한다.

참조에 의한 호출, call by reference

'참조에 의한 호출'은 함수의 매개 변수를 참조 타입으로 선언하여, 매개 변수가 함수를 호출 하는 쪽의 실인자를 참조하여 실인자와 공간을 공유하도록 하는 인자 전달 방식이다. 참조 타입으로 선언된 함수의 매개 변수를 참조 매개 변수라고 부른다.

  • 참조 매개 변수로 이루어진 모든 연산은 원본 객체에 대한 연산이 된다.
  • 참조 매개 변수는 이름만 생성되므로, 생성자와 소멸자는 아예 실행되지 않는다.

참조 리턴

참조 리턴이란, 변수 등과 같이 현존하는 공간에 대한 참조의 리턴




복사 생성자




5-8

스택에 저장할 수 있는 정수의 최대 개수는 생성자에서 주어지고 size 멤버에 유지한다.

main.cpp

#include "MyIntStack.h"
#include <iostream>
using namespace std;

void f(MyIntStack obj) {        //MyIntStack obj(a);와 같음. 복사 생성자 호출
    cout << "f() 호출" << "스택에 저장된 개수는 " << obj.getLength() << endl;
    //return
}

int main() {
    MyIntStack a(5);
    a.push(10);
    a.push(20);

    f(a);       //f(MyIntStack(a));와 같음. a를 인자로 넘겨줄 때 복사 생성자 호출
    //MyIntStack b = a;       //=MyIntStack b(a);와 같음. 복사 생성자 호출. a의 내용을 b에 복사

    //f(a);함수가 호출된 후에는 a와 f(a)가 같은 배열을 가리키게 되어서 f(a)가 소멸될 때 a의 배열도 소멸되어 pop할 때 오류가 발생함!!!!!!!!!

    int n;
    a.pop(n);
    cout << "pop한 값은 " << n << endl;
    a.pop(n);
    cout << "pop한 값은 " << n << endl;

    cout << endl;

    return 0;
}

MyIntStack.h

#ifndef MYINTSTACK_H
#define MYINTSTACK_H

//복사 생성자 중요해!!!!!!
class MyIntStack
{
    int *p;         //동적으로 할당할 배열을 가리킬 포인터
    //f(a);에서 복사 생성자 호출 시 p가 가리키는 배열을 복사하면서 문제가 발생할 수 있음!!!!!!! 두 객체가 같은 배열을 가리키게 되어서 하나의 객체가 소멸될 때 다른 객체도 소멸됨. 이를 얕은 복사라고 함. 샴쌍둥이와 같은 상황. 
    //*p를 새로운 포인터로 가리키게 하면 해결됨. 이를 깊은 복사라고 함.

    int size;       //스택의 크기
    int tos;        //저장할 위치를 가리키는 인덱스. 스택이 비어있을 때는 -1
public:
    MyIntStack(int size);
    MyIntStack(MyIntStack &src);      //복사 생성자(깊은 복사)
    ~MyIntStack();
    bool push(int n);       //bool은 성공 여부 반환을 위해
    bool pop(int &n);       //변수 n에 팝한 값을 저장. 왜 참조인가? 반환값으로 팝한 값을 전달할 수 없기 때문
    int getLength() { return tos; }    //스택의 길이 반환

};

#endif

MyIntStack.cpp

#include "MyIntStack.h"
#include <iostream>
using namespace std;

MyIntStack::MyIntStack(int size) {
    p = new int[size];
    if (!p) {
        cout << "메모리 할당 오류" << endl;  //memory alloc error
        exit(1);        //exit(0)은 정상 종료, exit(1)은 비정상 종료
    }
    tos = 0;
    this -> size = size;
}
MyIntStack::MyIntStack(MyIntStack &src) {
    tos = src.tos;
    size = src.size;
    p = new int[src.size];
    if (!p) {
        cout << "메모리 할당 오류" << endl;  //memory alloc error
        exit(0);        //exit(0)은 정상 종료, exit(1)은 비정상 종료
    }
    for (int i = 0; i < src.tos; i++) {
        p[i] = src.p[i];
    }
}

MyIntStack::~MyIntStack() {
    delete[] p;
}

bool MyIntStack::push(int n) {
    if (tos == 10) {        //full 
        return false;
    }
    p[tos++] = n;

    return true;            //not full OK
}

bool MyIntStack::pop(int &n) {
    if (tos == 0) {         //empty
        return false;
    }
    n = p[--tos];

    return true;            //not empty OK
}
profile
주니어 개발자

0개의 댓글