값에 의한 호출로 객체를 전달할 때 문제점
- 실인자 객체의 크기가 크면 객체를 복사하는 시간이 커지는 단점이 있다.
- 객체가 함수에 전달되면, 함수의 매개 변수 객체가 생성되고, 함수가 종료하면 매개 변수 객체가 소멸된다. 매개 변수 객체의 생성자와 소멸자가 모두 실행되지 않는다. 객체를 매개 변수로 가지는 함수의 경우, C++ 컴파일러는 매개 변수 객체의 생성자는 실행되지 않고 소멸자만 실행되도록 컴파일 한다.
-왜 매개 변수 객체의 생성자가 실행되지 않도록 컴파일 되는가?
>다음 코드는 반지름이 30인 waffle 객체를 생성하고, increase() 함수를 호출하여 waffle 객체를 전달한다.
Circle waffle(30);
increase(waffle);
increase() 함수의 매개 변수 c에 waffle 객체가 전달된 후, 만일 객체 c의 생성자 Circle()이 실행된다면, 객체 c의 반지름(radius 멤버 변수)이 1로 초기화되어, 전달 받은 원본의 상태를 잃어버리게 된다. 컴파일러는 이런 문제가 발생하지 않도록, 매개 변수 객체의 생성자가 실행되지 않도록 한다. 소멸자의 경우는 다르다. increase()가 리턴하면 c의 소멸자가 실행되고 c는 사라진다.
매개 변수 객체의 생성자가 실행되지 않고 소멸자만 실행되는 비대칭 구조는, 함수 호출 시 원본 객체의 상태를 그대로 매개 변수 객체에 전달되도록 하기 위한 것이지만, 중대한 문제를 동반한다. 이 문제점을 해결하기 위한 방법으로 복사 생성자를 설명한다.
복사 생성자 > '값에 의한 호출' 시, 컴파일러는 매개 변수 객체의 생성자 대신 복사 생성자가 호출되도록 컴파일하기 때문에, 생성자가 실행되지 않는 것이다. 컴파일러는 클래스에 복사 생성자가 작성되어 있지 않는 경우, 실인자 객체의 멤버 변수를 1:1로 매개 변수 객체에 복사하는 디폴트 복사 생성자를 자동으로 삽입한다.
주소에 의한 호출로 객체 전달
-주소에 의한 호출 과정
함수 호출 시 객체의 주소만 전달하는 '주소에 의한 호출'이 이루어지도록 increase()함수와 함수 호출 코드를 수정한 사례로서, '주소에 의한 호출' 과정을 자세히 보여준다.
increase()함수는 '주소에 의한 호출'이 일어나도록 다음과 같이 선언
void increase(Circle *p)
main() 함수에서 다음과 같이 increase()를 호출하면,
Circle waffle(30);
increase(&waffle); // waffle 객체의 주소를 전달한다.
waffle 객체의 주소가 포인터 p에 전달된다. p는 객체가 아니므로 생성자나 소멸자와 상관이 없다. 다음 코드가 실행되면, waffle 객체의 반지름이 1 증가된다.
p->setRadius(r+1);
-주소에 의한 호출의 특징
'값에 의한 호출'에 비해 원본 객체를 복사하는 시간 소모가 없으며, 매개 변수가 단순 포인터이므로, '값에 의한 호출' 시에 발생하는 생성자 소멸자의 비대칭 문제도 없다. 하지만, 매개 변수 포인터로 의도치 않게 원본 객체를 훼손할 가능성이 있다.
'Programming Language > C++' 카테고리의 다른 글
| 객체 치환 및 객체 리턴 (0) | 2023.04.08 |
|---|---|
| 함수의 인자 전달 방식 (1) | 2023.04.07 |
| 문자열 다루기 (0) | 2023.04.07 |
| string 클래스 개요 (0) | 2023.04.07 |
| this의 기본 개념 (0) | 2023.04.07 |