C++에서 복사생성자의 전달인자 선언시 const를 붙여주지 않아도 상관없다. 그러나 & 선언은 반드시 해줘야 한다.
& 선언이 없다면 무한루프에 빠져 버리기 때문이다. 다행히 대부분의 컴파일러는 & 선언을 해주지 않으면 컴파일
오류를 발생시켜 준다. 참으로 고마운 일이 아닐 수 없다. 그렇다면 왜 무한루프에 빠지게 되는 것일까?
다음 코드를 보기 바란다.
위 소스에서 네모친 부분이 복사생성자를 호출하는 부분이다.
여기서 &를 넣지 않는다면, 이는 Call by Reference 가 아닌, Call by Value가 된다.
즉, 값을 복사하여 그 값을 참조한다는 뜻이다. 하지만 문제는 지금부터 시작이다.
AAA객체를 복사하기 위해서는 객체생성 순서에 따라서 메모리를 할당하고 값을 복사하여야 한다.
다시 말해서 생성자를 호출하여야 한다는 의미다.
복사생성자 호출 -> 인자로 넘어가는 객체의 복사 -> 생성자, 복사생성자 호출 -> 그 복사생성자 안에서 또다시 객체 복사 -> 복사생성자 호출 -> ... 무한반복 ...
이렇게 복사생성자의 형식인자를 생성해야 하기 때문에 무한루프에 빠지게 된다. 역시 원인은 &를 빼면 Call by Value 라는 점에 있고, 레퍼런스를 쓰는 이유 중 하나이기도 하다.
※ 참고로 레퍼런스(&)를 사용한 Call by Reference로 인자를 넘겨주는 이유는 다음과 같이 크게 2가지이다.
1. &를 사용하지 않고 포인터를 사용하면 포인터 연산이 가능하기 때문에 잘못된 메모리 접근을 할 가능성이 높아진다.
아래의 코드는 에러를 나타낼 것이다.
--------------------------------------------------------------------------------------------------------
void swap(int *a, int *b)
{
int temp = *a;
a++; // 잘못 들어간 코드
*a = *b;
*b = temp;
}
--------------------------------------------------------------------------------------------------------
경우에 따라서는 포인터 연산이 가능하다는 것이 단점으로 작용한다.
2. 약간의 성능향상이 가능하다.
Call by Value로 크기가 큰 구조체같은 데이터를 함수 인자로 넘겨주면 함수의 호출이 부담스러울 수 밖에 없다.
Call by Value의 기본 방식이 복사이기 때문이다.
이러한 부담을 레퍼런스가 해결해 줄 수 있다. 레퍼런스의 형태로 받게 되면, 변수 주소만 복사해 가는 것이지, 데이터 자체가 복사되는 것이 아니기 때문이다.
→ 그렇다면, 레퍼런스(&)를 사용하여 Call by Reference로 함수 인자를 넘기는 것이 무조건 좋은 것인가??
꼭 그렇지는 않다. 다음의 코드를 보자
--------------------------------------------------------------------------------------------------------
void swap(int &a, int &b)
{
int temp = a;
a = b;
b = temp;
}
int main(void)
{
...
swap(val1, val2);
...
}
--------------------------------------------------------------------------------------------------------
대충 눈치를 채셨겠지만, 이것만 봐서는 도대체 이 swap 함수가 Call by Value인지 Call by Reference인지 감을 잡지 못한다.
프로그램의 길이가 엄청 긴 경우에는 더욱 헷갈릴 것이다.
Call by Reference의 적절한 사용은 프로그래머의 선택이다. ^^
출처 : http://blog.naver.com/damby0?Redirect=Log&logNo=50023611792
'Programming > C++' 카테고리의 다른 글
C/C++언어 함수들 (0) | 2011.08.22 |
---|---|
교차 포함 시 대량의 오류가 발생하는 경우 (0) | 2011.04.26 |