'매개변수가 한 개인 생성자' 를 다른 말로 '변환 생성자' 라고도 한다. 문제는 이 변환 생성자가 은근슬쩍 호출되거나 불필요한 임시 객체를 만들어냄으로써 프로그램의 효율을 갉아먹는 원인이 된다는 것이다.
#include <iostream>
using namespace std;
// 제작자 코드
class Rain
{
public:
// 매개변수가 하나뿐인 생성자는 형변환이 가능하다.
Rain(int Param) : Data(Param)
{
cout<< "Rain(int)"<< endl;
}
Rain(const Rain &rhs) : Data(rhs.Data)
{
cout << "Rain(const Rain &rhs)" << endl;
}
int GetData() const { return Data; }
void SetData(int Param) { Data = Param; }
private:
int Data = 0;
};
// 사용자 코드
// 매개변수가 클래스 형식이며 변환 생성이 가능하다.
void TestFunc(Rain param)
{
cout << "TestFunc(): " << param.GetData() <<endl;
}
int main(void)
{
// int 자료형에서 Rain 형식으로 변환될 수 있다.
TestFunc(5);
return 0;
}
실행결과
TestFunc() 함수의 매개변수는 Rain 클래스 형식이다. 그리고 Rain 클래스는 int 자료형에 대한 변환 생성자 (Rain(int))를 제공한다. 그렇기 때문에 38번행의 TestFunc(5); 라는 코드를 작성할 수 있게 되었다.
그렇다면 소멸자를 추가하고 31번행의 매개변수를 참조형식으로 바꿔주게 되면 어떻게 될까?
#include <iostream>
using namespace std;
// 제작자 코드
class Rain
{
public:
// 매개변수가 하나뿐인 생성자는 형변환이 가능하다.
Rain(int Param) : Data(Param)
{
cout<< "Rain(int)"<< endl;
}
Rain(const Rain &rhs) : Data(rhs.Data)
{
cout << "Rain(const Rain &rhs)" << endl;
}
~Rain()
{
cout << "~Rain()" << endl;
}
int GetData() const { return Data; }
void SetData(int Param) { Data = Param; }
private:
int Data = 0;
};
// 사용자 코드
// 매개변수가 클래스 형식이며 변환 생성이 가능하다.
void TestFunc(const Rain ¶m)
{
cout << "TestFunc(): " << param.GetData() <<endl;
}
int main(void)
{
cout << "시작" << endl;
// 새로운 Rain 객체를 생성하고 참조를 전달한다.
TestFunc(5);
// 함수가 반환되면서 임시 객체는 소멸한다.
cout << "끝" << endl;
return 0;
}
실행결과
결과를 보면 분명히 변환 생성자가 호출 됐음을 확인할 수 있다. 그런데 main()함수의 어디에도 Rain 클래스 객체를 선언하거나 동적으로 생성하는 코드가 전혀없다! -> 컴파일러가 '알아서' 임시 객체를 생성한 후 이 임시 객체에 대한 참조가 TestFunc() 함수로 전달되도록 했다. 그리고 임시 객체는 TestFunc() 함수를 반환함과 동시에 소멸시켰다. 즉, TestFunc(5); 라는 코드가 실제로 TestFunc(Rain (5)); 라고 쓴것과 동일해진 것이다.
댓글