덧. 제 답변이 충분하지 않다고 여기시는 분이 두 분이나 나왔으니 좀 덧붙여야겠군요.
제시된 상황이 왜 무한루프에 빠지는지에 대해서는 충분히 설명이 됐다고 생각합니다만,
Q. 복사 생성자의 매개 변수가 참조형이 아닐 때도 복사 생성자라고 할 수 있는가?
A. 엄밀히 따지면, 아닙니다.
표준에 따르면, class X의 템플릿 함수가 아닌 생성자가 복사 생성자이기 위해서는 반드시 첫 번째 파라미터의 타입이 X&, const X&, volatile X&, constvolatile X& 중 하나여야 합니다.
따라서 파라미터가 참조형이 아닐 경우에는 복사 생성자라고 할 수 없습니다. 그냥 생성자일 뿐이죠.
참조 : C++11 std 12.8.2
Q. 그러면, 그런 형태의 생성자가 어떤 쓸모가 있는가?
A. 쓸모가 없습니다. 게다가 표준에 어긋나기까지 합니다.
표준에 따르면 class X의 생성자로 X 타입의 파라미터 하나만 받는 생성자를 선언하는 것은 ill-formed입니다.
일반적으로 T를 받는 함수와 T&를 받는 함수가 오버로딩이 안 되는 것은 아닙니다. 물론 거기서 const T&를 받는 함수도 같이 선언할 수 있습니다.
하지만 그런 식으로 오버로딩을 할 경우 대개 Overload resolution을 할 때 문제가 생기게 됩니다. 어느 함수를 부를지 확실해지지 않는 모양으로 호출하려 할 경우 에러가 발생하기 때문이지요.
그런 의미에서, 사실 T를 받는 생성자도 선언해서 사용 가능할 거라고 생각했는데 제 생각이 틀린 모양이군요. 표준에 의하여 implicit copy constructor가 생성되고 (12.8.2, 12.8.7~8) overload resolution에서 이슈가 생길 줄 알았는데, 아예 표준에서 T를 받는 생성자 선언 자체를 틀어막았기 때문에(12.8.6) 그 단계까지 가지도 않습니다. 실제로 제가 가진 컴파일러들은 전부 그런 생성자의 선언에서 에러를 내는군요.
그러니 개념서의 해당 부분은 "이론적으로 복사 생성자에서 파라미터가 참조형이 아닌 경우를 허용하면 무한 루프가 발생하게 된다. 그러므로 허용하지 않는다."로 읽는 편이 바람직하겠습니다. 개념상으로는 무한루프가 발생할 수 있는 상황이지만 실제로는 그러한 프로그램의 컴파일을 막는 규칙이 있는 것이니까요.
왜냐하면 무한루프이기 때문이죠.
왜냐하면 무한루프이기 때문이죠.
1. 외부에서 객체를 복사 생성한다.
2. 복사 생성을 위해 복사 생성자가 호출된다.
3. 복사 생성자가 원본을 참조로 받지 않고 값으로 전달받는다.
4. 함수가 매개변수를 값으로 전달받을 경우 호출하는 쪽으로부터 매개변수가 복사 생성된다.
5. goto 2
덧. 제 답변이 충분하지 않다고 여기시는 분이 두
덧. 제 답변이 충분하지 않다고 여기시는 분이 두 분이나 나왔으니 좀 덧붙여야겠군요.
제시된 상황이 왜 무한루프에 빠지는지에 대해서는 충분히 설명이 됐다고 생각합니다만,
Q. 복사 생성자의 매개 변수가 참조형이 아닐 때도 복사 생성자라고 할 수 있는가?
A. 엄밀히 따지면, 아닙니다.
표준에 따르면,
class X
의 템플릿 함수가 아닌 생성자가 복사 생성자이기 위해서는 반드시 첫 번째 파라미터의 타입이X&
,const X&
,volatile X&
,const volatile X&
중 하나여야 합니다.따라서 파라미터가 참조형이 아닐 경우에는 복사 생성자라고 할 수 없습니다. 그냥 생성자일 뿐이죠.
참조 : C++11 std 12.8.2
Q. 그러면, 그런 형태의 생성자가 어떤 쓸모가 있는가?
A. 쓸모가 없습니다. 게다가 표준에 어긋나기까지 합니다.
표준에 따르면
class X
의 생성자로X
타입의 파라미터 하나만 받는 생성자를 선언하는 것은 ill-formed입니다.참조 : C++11 std 12.8.6
조금 더.
조금 더.
일반적으로
T
를 받는 함수와T&
를 받는 함수가 오버로딩이 안 되는 것은 아닙니다. 물론 거기서const T&
를 받는 함수도 같이 선언할 수 있습니다.하지만 그런 식으로 오버로딩을 할 경우 대개 Overload resolution을 할 때 문제가 생기게 됩니다. 어느 함수를 부를지 확실해지지 않는 모양으로 호출하려 할 경우 에러가 발생하기 때문이지요.
그런 의미에서, 사실
T
를 받는 생성자도 선언해서 사용 가능할 거라고 생각했는데 제 생각이 틀린 모양이군요. 표준에 의하여 implicit copy constructor가 생성되고 (12.8.2, 12.8.7~8) overload resolution에서 이슈가 생길 줄 알았는데, 아예 표준에서T
를 받는 생성자 선언 자체를 틀어막았기 때문에(12.8.6) 그 단계까지 가지도 않습니다. 실제로 제가 가진 컴파일러들은 전부 그런 생성자의 선언에서 에러를 내는군요.그러니 개념서의 해당 부분은 "이론적으로 복사 생성자에서 파라미터가 참조형이 아닌 경우를 허용하면 무한 루프가 발생하게 된다. 그러므로 허용하지 않는다."로 읽는 편이 바람직하겠습니다. 개념상으로는 무한루프가 발생할 수 있는 상황이지만 실제로는 그러한 프로그램의 컴파일을 막는 규칙이 있는 것이니까요.
인스턴스가 함수의 인자로 들어갈 때 복사가 되기
인스턴스가 함수의 인자로 들어갈 때 복사가 되기 때문이죠 call by value call by reference 참조하세요
인스턴스가 함수의 인자로 들어갈 때 복사가 되기
인스턴스가 함수의 인자로 들어갈 때 복사가 되기 때문이죠 call by value call by reference 참조하세요
단서를 달아보겠습니다.
classname obj2=obj1;
이 부분에서 생성자가 호출되죠.
아래와 같은 참조는 생성자가 호출되지 않을 겁니다.
classname &obj4=obj2;
아래 코드 붙여봅니다.
-test208.h-
-test208.cpp-
댓글 달기