복사 생성자의 매개 변수가 참조형이 아닌때 무한루프가 드는 이유가 무었인가요?

gusrbs82의 이미지

안녕하세요.

휴학을 하고 한동안 코딩을 잡지 않다가 다시 보고 있는 학생입니다.

기본 개념서를 보며 기억을 떠올리고 있긴한데요.

읽다가

"복사 생성자의 매개 변수가 참조형이 아닐때엔 무한루프가 발생한다.

꼭 참조형을 사용하세요."라는 문구를 봤는데.

내부적으로 왜 무한루프가 일어나는지 이해를 잘 못하겠어서요.

왜 그런건가요???

 의 이미지

왜냐하면 무한루프이기 때문이죠.

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) 그 단계까지 가지도 않습니다. 실제로 제가 가진 컴파일러들은 전부 그런 생성자의 선언에서 에러를 내는군요.

그러니 개념서의 해당 부분은 "이론적으로 복사 생성자에서 파라미터가 참조형이 아닌 경우를 허용하면 무한 루프가 발생하게 된다. 그러므로 허용하지 않는다."로 읽는 편이 바람직하겠습니다. 개념상으로는 무한루프가 발생할 수 있는 상황이지만 실제로는 그러한 프로그램의 컴파일을 막는 규칙이 있는 것이니까요.

jehnpark의 이미지

인스턴스가 함수의 인자로 들어갈 때 복사가 되기 때문이죠 call by value call by reference 참조하세요

jehnpark의 이미지

인스턴스가 함수의 인자로 들어갈 때 복사가 되기 때문이죠 call by value call by reference 참조하세요

mydream의 이미지

classname obj2=obj1;

이 부분에서 생성자가 호출되죠.
아래와 같은 참조는 생성자가 호출되지 않을 겁니다.

classname &obj4=obj2;

아래 코드 붙여봅니다.
-test208.h-

#ifndef TEST_H
#define TEST_H
 
class Test {
public:
	Test();
	Test(const Test& right);
};
#endif

-test208.cpp-
#include "test208.h"
#include <cstdio>
Test::Test() {
	printf("Test()\n");
}
Test::Test(const Test& right) {
	printf("Test(const Test& right)\n");
}
int main() {
	Test t1;//기본생성자 호출
	Test t2=t1;//복사생성자 호출
	Test& t3=t2;//어떤 생성자도 호출되지 않습니다.
 
	return 0;
}

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.