💻 개인공부 💻/C | C++

[C++] 함수와 참조 (feat. &, 별명)

공대생 배기웅 2020. 6. 24. 04:13
반응형

출처 => C++ How to Program (Detitel / Prenticehall) / 현재 그리고 미래지향적인 C++ 프로그래밍(장석우, 임정목 / 비앤씨에듀케이션)

함수의 인자 전달 방식

 

▶ 프로그래밍에서 함수를 사용할 때 변수, 즉 인자는 거의 필수 불가결하게 사용이 된다. 인자, 혹은 이 매개변수는 어떤 식으로 불러와서 사용이 되는걸까? 2가지의 방법이 있는데 값에 의한 호출주소에 의한 호출로 나뉘어진다.

 

값에 의한 호출로 객체 전달

 

▶ 순서는 다음과 같다.

 

1. 함수를 호출하는 쪽에서 객체를 전달한다. 

2. 함수의 매개 변수 객체 생성, 매개 변수 객체의 생성자는 호출되지 않는다.

3. 함수 종료, 매개 변수 객체의 소멸자를 호출한다.

 

▶ 값에 의한 호출 시, 매개 변수 객체의 생성자는 실행되지 않는데 그 이유는 호출되는 순간의 실인자 객체 상태를 매개 변수 객체에 그대로 전달하기 위해서이다. 

 

#include<iostream>
using namespace std;

class Circle {
	int radius;
public:
	Circle() {
		radius = 1;
		cout << "생성자 실행 radius=" << radius << endl;
	}
	Circle(int r) {
		this->radius = radius;
		cout << "생성자 실행 radius=" << radius << endl;
	}
	~Circle() {
		cout << "소멸자 실행 radius=" << radius << endl;
	}
	double getArea() {
		return 3.14 * radius * radius;
	}
	int getRadius() {
		return radius;
	}
	void setRadius(int radius) {
		this->radius = radius;
	}
};

void increase(Circle c) {
	int r = c.getRadius();
	c.setRadius(r + 1);
}

void main() {
	Circle waffle(30);
	increase(waffle);
	cout << waffle.getRadius() << endl;
}

 

▶ 코드 분석 시간! main( ) 함수에서부터 보자.

Circle waffle(30);
increase(waffle);

 

▶ Circle의 기능을 갖는 객체 waffle을 생성하였다. waffle의 반지름은 30이다. 이 waffle을 increase라는 매개변수로 넣어준다.(값에 의한 호출)

void increase(Circle waffle){
	int r=c.getRadius();
	c.getRadius(r+1);
}

 

▶ waffle의 반지름은 30이다. getRadius()메서드는 반지름을 int형으로 return 하므로 c.getRadius()의 값은 30이다.

 

▶ r+1이므로 c.getRadius(r+1)의 값은 31이다.

 

▶ 클래스 Circle의 객체인 waffle이 만들어지면서 생성자가 실행되었다. (1 번째 줄), 그리고 increase 메소드의 객체 c가 종료가 되면서 소멸자가 실행이 되고 그 때의 반지름은 r+1인 31이다. (2 번째 줄). 그리고 waffle.getRadius()의 결과인 30을 cout 명령어를 통해 출력한다. (3 번째 줄). 그리고 마지막으로 waffle객체가 종료가 되면서 소멸자가 실행이 된다. 이 때 waffle의 반지름은 30이다. (4 번째 줄)

 

주소에 의한 호출로 객체 전달

 

▶ 함수 호출시 객체의 주소만 전달하여 준다. 이 때의 함수의 매개변수는 객체에 대한 포인터 변수로 선언을 해준다.

void increase(Circle *c) {
	int r = c->getRadius();
	c->setRadius(r + 1);
}

void main() {
	Circle waffle(30);
	increase(&waffle);
	cout << waffle.getRadius() << endl;
}

 

▶ Class에 대한 내용은 같고, 주소로 호출을 하게 되면 위의 코드만 바뀐다. 

 

 

참조 변수

 

▶ 이미 존재하는 변수에 대한 다른 이름(별명)을 선언하는 개념이다.

 

▶ 참조 변수는 이름만 생기며 참조변수에 대한 새로운 공간을 할당하지 않는다. 또한 초기화로 지정된 기존 변수를 공유한다.

int n = 2;
int& refn = n;
//참조변수 refn 선언. refn은 n에 대한 별명

Circle c;
Circle& refc = c;
//참조변수 refc선언. refc는 circle에 대한 별명

 

기본 타입 변수에 대한 참조 예제

 

#include<iostream>
using namespace std;

void main() {
	cout << "i" << '\t' << "n" << '\t' << "refn" << endl;
	int i = 1;
	int n = 2;
	int& refn = n;
	//참조변수 refn선언. refn은 n에 대한 별명
	n = 4;
	refn++;//refn=5, n=5;
	cout << i << '\t' << n << '\t' << refn << endl;

	int* p = &refn;
	//p는 n의 주소를 가짐
	*p = 20;//refn=20, n=20
	cout << i << '\t' << n << '\t' << refn << endl;
}

 

 

 

 

객체에 대한 참조 예제

#include<iostream>
using namespace std;

class Circle {
	int radius;
public:
	Circle() { radius = 1; }
	Circle(int radius) {
		this->radius = radius;
	}
	void setRadius(int radius) {
		this->radius = radius;
	}
	double getArea() {
		return 3.14 * radius * radius;
	}
};

void main() {
	Circle c;
	Circle& refc = c;
	refc.setRadius(10);
	cout << refc.getArea() << " " << c.getArea();
	//refc나 c나 같기 때문에 결과는 314로 같다
}

 

 

참조에 의한 호출

 

▶ 참조를 가장 많이 활용하는 사례로써 call by reference라고 부른다

 

참조에 의한 호출 예제

#include<iostream>
using namespace std;

class Circle {
	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 increaseCircle(Circle& c) {//참조 매개변수 c
	int r = c.getRadius();
	c.setRadius(r+1);
}

void main() {
	Circle waffle(30);
	increaseCircle(waffle);//참조에 의한 호출
	cout << waffle.getRadius() << endl;
}

 

 

728x90
반응형