1. 값에 의한 호출방법 : 값에 의한 호출은 실인자의 값을 함수 매개 변수에 복사한다. 매개변수와 실인자는 서로 다른 공간을 독립적으로 사용한다. 그렇기 때문에 함수 내에서 실인자를 손상 시키는 일은 없다.
2. 주소에 의한 호출방법 : 주소에 의한 호출은 함수 호출 시 주소가 매개 변수로 전달된다. 매개변수와 실인자는 공간을 공유한다. 실인자의 주소를 넘겨주어 의도적으로 함수 내에서 실인자의 값을 변경하고자 할 때 이용 될 수 있다.
3. 참조에 의한 호출방법 : 참조 변수를 선언하여 사용한다. 참조 변수를 선언할때는 &기호를 사용한다. 참조 변수란 이미 선언된 변수에 대한 별명(alias)이다. 참조 변수가 선언될 시 이름만 생성되며 별도의 공간이 할당되지 않는데 원본 변수의 공간을 공유한다.
참조 변수 선언 시 주의 사항이 있는데, 어떤 변수에 대한 참조인지 초기화를 시켜주어야 한다. 그리고 참조 변수는 공간을 별도로 할당하지 않기 때문에 배열을 만들 수 없다.
4. 값에 의한 호출 예(예제 5-1, 값에 의한 호출의 문제점 정리)
#include <iostream>
using namespace std;
class Circle {
private:
int radius;
public:
Circle();
Circle(int r);
~Circle();
double getArea() { return 3.14*radius*radius; }
int getRadius() { return radius; }
void setRadius(int radius) { this->radius = radius; }
};
Circle::Circle() {
radius = 1;
cout << "생성자 실행 radius = " << radius << endl;
}
Circle::Circle(int radius) {
this->radius = radius;
cout << "생성자 실행 radius = " << radius << endl;
}
Circle::~Circle() {
cout << "소멸자 실행 radius = " << radius << endl;
}
// 값에 의한 호출의 문제점 : 객체를 매개 변수로 가지는 함수의 경우 기본 생성자를 실행하여야 하는데 생성자는
// 실행되지 않고 소멸자만 실행되어지는 문제점이 발생한다. (생성자 소멸자의 비대칭 문제)
void increase(Circle c) { // c라는 독립적인 공간을 사용하기 때문에
int r = c.getRadius(); // 매개변수에는 다시 선언하며 받아준다.
c.setRadius(r+1); // 하지만 생성자는 호출하지 않는다.
} // 눈에 보이지 않지만 복사 생성자란 녀석이 있음
int main(int argc, char** argv) {
Circle waffle(30);
increase(waffle);
cout << waffle.getRadius() << endl;
system("pause");
return 0;
}
5. 참조에 의한 호출 예제(예제 5-3, 소스, 결과, 주석)
#include <iostream>
using namespace std;
int main(int argc, char** argv) {
cout << "i" << '\t' << "n" << '\t' << "refn" << endl;
int i = 1;
int n = 2;
int &refn = n; //참조변수 refn을 선언. refn은 n의 별칭과 같은 것이다.
n=4; //refn은 n의 공간을 공유하기 때문에 n이 4가 되면 refn도 4가 된다.
refn++; //refn이 1이 증가하면 n도 증가, 5 와 5가 된다.
cout << i << '\t' << n << '\t' << refn << endl; // 1 5 5
refn = i; //refn에 i의 값을 대입시킨다.refn과 n 그리고 i 모두 1이 된다.
refn++; //refn이 증가하면 n도 같이 증가한다. refn과 n은 2가 된다.
cout << i << '\t' << n << '\t' << refn << endl; // 1 2 2
int *p = &refn; //p가 refn의 주소를 가진다. 즉 p는 n의 주소를 가진다.
*p = 20; //p가 가르키는 곳이 20이 된다. 즉 refn과 n 둘다 20이 된다.
cout << i << '\t' << n << '\t' << refn << endl; // 1 20 20
return 0;
}
6. 참조에 의한 호출의 장점(예제 5-5, 소스, 결과, 주석)
#include <iostream>
using namespace std;
bool average(int a[], int size, int &avg){ //참조 매개 변수 avg를 사용
if(size <= 0){
return false;
}
int sum = 0;
for(int i=0 ; i<size ; i++){
sum += a[i];
}
avg = sum/size;
return true;
}
int main(int argc, char** argv) {
int x[] = {0,1,2,3,4,5};
int avg;
if(average(x, 6, avg)){ //참조 매개 변수를 사용하기 때문에 간단히 변수를 넘겨주기만 하면 값이 실제로도 바뀌기 때문에 좋다.
cout << "평균은 " << avg << endl; //함수 내에서도 참조 매개 변수를 보통 변수처럼 사용 하기 때문에 작성하기 쉽고 보기 좋은 코드가 된다는 장점이 있다.
}
else
cout << "매개 변수 오류 " << endl;
if(average(x, -2, avg)){
cout << "평균은 " << avg << endl;
}
else
cout << "매개 변수 오류 " << endl;
return 0;
}
'basic > C++' 카테고리의 다른 글
7. 프렌드와 연산자 중복 (비어있습니다) (0) | 2018.05.17 |
---|---|
6. 함수중복과 static멤버 (0) | 2018.05.15 |
4. 객체 포인터와 객체배열, 객체의 동적생성 (0) | 2018.04.10 |
3. 클래스와 객체 (0) | 2018.03.22 |
2. C++ 프로그래밍의 기본 (0) | 2018.03.13 |