참조 '&' 란, 이미 선언된 변수에 대한 별명(alias)으로, 선언 시 반드시 원본 변수로 초기화하여야 한다.
- 참조 변수
- 참조에 의한 호출
- 함수의 참조 리턴
int n=2; Circle circle;
int &refn = n; Circle &refc = circle;
참조 변수가 선언되면, 참조 변수 이름만 생성되며, 별도의 공간이 할당되지 않고 원본 변수의 공간을 공유한다.
'참조에 의한 호출'은 함수의 매개 변수를 참조 타입으로 선언하여, 매개 변수가 함수를 호출 하는 쪽의 실인자를 참조하여 실인자와 공간을 공유하도록 하는 인자 전달 방식이다. 참조 타입으로 선언된 함수의 매개 변수를 참조 매개 변수라고 부른다.
참조 리턴이란, 변수 등과 같이 현존하는 공간에 대한 참조의 리턴
스택에 저장할 수 있는 정수의 최대 개수는 생성자에서 주어지고 size 멤버에 유지한다.
#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;
}
#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
#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
}