C++Builder Programming Forum
C++Builder  |  Delphi  |  FireMonkey  |  C/C++  |  Free Pascal  |  Firebird
볼랜드포럼 BorlandForum
 경고! 게시물 작성자의 사전 허락없는 메일주소 추출행위 절대 금지
C++빌더 포럼
Q & A
FAQ
팁&트릭
강좌/문서
자료실
컴포넌트/라이브러리
메신저 프로젝트
볼랜드포럼 홈
헤드라인 뉴스
IT 뉴스
공지사항
자유게시판
해피 브레이크
공동 프로젝트
구인/구직
회원 장터
건의사항
운영진 게시판
회원 메뉴
북마크
볼랜드포럼 광고 모집

C++빌더 강좌/문서
C++Builder Programming Tutorial&Docments
[100] [KTS의 C++빌더] 생성자와 대입 치환연산자 문제
김태선 [jsdkts] 15639 읽음    2006-06-01 22:41
제 마음대로 쓰는 C++빌더 강좌입니다.
시간나는대로 틈틈히 C++빌더의 내공을 높이기 위해 강좌를 쓸 생각입니다.
목차를 중급에서 고급까지 잡아봤지만,
업무가 있어 그대로 할수는 없고 그냥 틈나는대로 생각나는대로 올리겠습니다.

C++빌더의 저변확대를 위해서는 C++빌더 텍스트가 좋은게 있어야 하는데
부족한 것 같아, 책 대신 쓰는 것입니다. 서문도 나중에 다시 쓰겠습니다.
//---------------------------------------------------------------------------
// 김태성의 C++빌더 강좌: 클래스 생성자와 대입연산자 문제.
//---------------------------------------------------------------------------
오늘은 객체의 생성과 대입/치환에 대해 간단히 알아 보겠습니다.
초급은 좀 어려울지도 모르겠네요.

String s;

이건 String::String()  또는 String::String(anytype var = default) 생성자가 실행되겠죠
머... 그냥 String형 변수 - 정확하게는 String 클래스 인스턴스 s 가 초기화 되겠죠.

String s("테스트");

이건 어떨까요?
String::String(char *str); 생성자가 실행되겠죠.

String s = "테스트";

이건 어떻게 될까요?
s 가 초기화 된 후 = 대입연산자가 실행될까요? 아니면 ?
위 구문은 바로
String::String(char *str);
생성자가 실행됩니다.

String s("테스트");
String s = "테스트";
이 둘의 표현은 완전히 같게 처리됩니다. 컴파일러 입장에서는 완전히 같은 것입니다.
이렇게 되는 이유는 s 가 객체로 메모리에 자리를 잡기 전이므로 자리를 잡기 위해 생성자를 호출하는 까닭입니다.

이는 다른 형태의 클래스를 임의로 설계해서 테스트 해봐도 금방 알수 있습니다.

struct TA
{
    int  m_a;
    int  m_b;
    int  m_c;
    String m_str;
    TA(int seed) { m_a = seed; }; 
};

TA  a(1);
TA  a = 1;

위 두 문장은 완전히 같습니다.

그러면 다음 문장을 볼까요?

String s = "단군조선이 44대에 대부여로 나라이름을 바꾼후 47대 단군에서 망하고, 해모수가 정통을 이어 북부여를 건국함.";
s = "북부여의 정통을 이어 고구려를 건국한 고주몽, 고주몽은 해모수 후손이지 아들이 아니라우";

첫번째 문장은 이제 이해가 되죠.
두번째 문장은 어떻게 처리될까요?
두번째 문장은 이미 s 가 객체로 메모리에 자리를 잡고 있습니다.
그러므로 "북부여... 아들이 아니라우" 문자열을 바로 대입할 방법이 없습니다.
그래서 먼저 String::String(char *) 생성자로 임시 객체가 생성됩니다.
생성된 임시 객체에서 s 객체로 내용을 복사하는 작업을 합니다.
이때의 복사는 단순한 메모리 내용 복사(대입 과정이죠)가 있고, 특별히 대입에 대한 처리를
필요로 하는 것은 = 대입연산자(또는 치환연산자)가 작동합니다.

그러므로 두번째 줄은 다음과 같습니다.
s = String("북부여의 정통을 이어 고구려를 건국한 고주몽, 고주몽은 해모수 후손이지 아들이 아니라우");

대입연산자 = 을 오버로딩해서 처리해야 하는 경우는
클래스가 별도로 관리하는 메모리가 있는 경우입니다.
또는 생성과 소멸에 있어서 특별한 처리를 하는 경우입니다.
그래서 위에서 두번째 문장은
String::String& operator=(const String & src);
과 같은 연산자 오버로딩 함수가 호출되어 처리되어 집니다.
왜냐하면 임시객체에서 이미 자리를 잡고 있는 s 객체로 단순히 메모리를 복사하면
s 가 이미 할당받아 가지고 있던 메모리를 해제하지 못해
메모리 누수가 일어나기 때문입니다.

TA  a = 1;
a = 2;

이 경우 두번째 줄은 어떻게 될까요?
TA는 = 대입연산자를 오버로딩하지 않았습니다. 그러므로 그냥 임시객체에서 a 객체로
단순 메모리 복사가 일어납니다. 멤버변수중에 m_str은 String 클래스이고 String클래스는
이미 = 대입연산자가 오버로딩되어 있으므로 String m_str; 부분만은 String 클래스의
= 대입연산자가 작동합니다. 나머지부분은 그냥 메모리 복사가 일어나죠.

두번째 줄은 역시 다음과 같습니다.
a = TA(2);

모든 클래스의 대입문은 이런식으로 처리됩니다.

위에서 주의할 것은 String 클래스는 위과 같은 식으로 처리하는 것은 맞지만
실제의 구현부는 약간의 차이가 있으므로 원리적인 것만 이해하시기 바랍니다.

그러면 왜 이런 것을 알아야 할까요?
이걸 모르면 클래스를 제대로 설계할 수가 없습니다.
특히 대입/치환이 일어난 경우에 대비를 할수가 없게 됩니다.

그냥 알아도 되고, 몰라도 되는 그런 것이 아니고 반드시 알아야할 사항입니다.


강좌가 좀 엉성한데... 점차 다듬어 나가겠습니다.
양해 바랍니다.

+ -

관련 글 리스트
100 [KTS의 C++빌더] 생성자와 대입 치환연산자 문제 김태선 15639 2006/06/01
Google
Copyright © 1999-2015, borlandforum.com. All right reserved.