'매개변수가 한 개인 생성자' 를 다른 말로 '변환 생성자' 라고도 한다. 문제는 이 변환 생성자가 은근슬쩍 호출되거나 불필요한 임시 객체를 만들어냄으로써 프로그램의 효율을 갉아먹는 원인이 된다는 것이다.
#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)); 라고 쓴것과 동일해진 것이다.
앞서 복사 생성자를 말하면서 강조했던 것은 매개변수로 사용할 거라면 무조건 참조 형식을 사용하라 했다. -> https://j-ra1n.tistory.com/entry/%EB%B3%B5%EC%82%AC-%EC%83%9D%EC%84%B1%EC%9E%90
이제는 하나 더 붙여서 묵시적 변환 생성자를 지원하는 클래스인지 꼭 확인해야한다. 내부적으로 메모리를 동적 할당하는 등 덩치가 제법 나가는 객체라면 묵시적 변환 생성자가 사용자 모르게 호출될 가능성을 차단하는 것이 바람직하다!!
// 제작자 코드
class Rain
{
public:
// 매개변수가 하나뿐인 생성자는 형변환이 가능하다.
// 하지만 묵시적으로 불가능하도록 차단한다.
explicit Rain(int Param) : Data(Param)
{
cout << "Rain(int)" << endl;
}
....
이 코드를 보면 explicit 예약어를 확인할 수 있다. 이것을 사용하면 임시 객체가 생성되지 못하게 막는다.

따라서 TestFunc(5); 같은 코드는 허용되지 않는다. 무조건 임시 객체가 생성된다는 사실이 명확하게 드러나는 TestFunc(Rain (5)); 형태로 작성해야한다.
'Develop > C++' 카테고리의 다른 글
[C++] cin, getline 함수 (0) | 2023.02.20 |
---|---|
[C ++] r-value 참조 (0) | 2023.02.20 |
[C ++] 복사 생성자 (0) | 2023.02.04 |
[C ++] 상수형 메소드 (1) | 2023.02.03 |
[C ++] 생성자와 소멸자 (0) | 2023.02.03 |
댓글