서적 정리/Effective C++

26.변수 정의는 늦출 수 있는 데까지 늦추는 근성을 발휘하자

민돌이2 2021. 12. 17. 17:04

변수를 정의하면 생성자와 소멸자가 호출되는 비용은 피해갈수 없다.

사용하지 않는 변수를 정의했을 때도 당연히 비용을 지출하는데, 이런 비용은 의미없는 비용이니 피해야한다.

 

비밀번호가 충분히 길 경우 해당 비밀번호를 암호화하여 반환하는 함수가 있다.

string encryptPassword(const string& password)
{
	string encrypted;
	size_t minimumPasswordLength = 10;

	if (password.length() < minimumPasswordLength)
		throw logic_error("Password is too short");
	
	...

	return encrypted;
}

비밀번호가 너무 짧으면 logic_error타입(54장 참고)의 예외를 던지도록 구현되어 있다.

이 함수에서 encrypted 변수는 예외가 발생시 사용되지 않을 변수이다. 즉, 예외를 던지더라도 의미없는 비용을 하고 있다. 이런 무의미한 비용지출을 막기 위해서 encrypted 변수의 정의는 꼭 필요해지기 전까지 미루는 편이 낫다고 생각할 수 있다.

string encryptPassword(const string& password)
{
	size_t minimumPasswordLength = 10;

	if (password.length() < minimumPasswordLength)
		throw logic_error("Password is too short");

	string encrypted;
	
	...

	return encrypted;
}

 

또한 생각해야 할것은 초기화와 대입의 차이다(4장 참고). 변수를 직접 초기화하는 방법이 생성하고 나서 값을 대입하는 방식보다 효율이 좋기 때문에 정의할 때 초기화해주는 것을 잊지 말자.

string encryptPassword(const string& password)
{
	...
	
	string encrypted(password);
	encrypt(encrypted);

	return encrypted;
}

void encrypt(string& str)
{
	... //비밀번호를 암호화
}

 

루프(Loop)에서 변수 정의시기는 언제가 효율적일까?

1.루프 바깥쪽에 정의

Widget w;
for (int i = 0; i < n; i++)
{
	w = i;
}

생성자 1번 + 소멸자 1번 + 대입 n번

 

2.루프 안쪽에 정의

for (int i = 0; i < n; i++)
{
	Widget w(i);
}

생성자 n번 + 소멸자 n번

 

대입 비용 < 생성자 비용 + 소멸자 비용 => 1번

대입 비용 > 생성자 비용 + 소멸자 비용 => 2번

클래스의 상황을 보고 결정하면 될 것 같다.

1번 방법은 w 객체의 유효범위가 루프를 포함한 함수가 종료될 때 까지고, 2번의 유효범위는 루프 한바퀴 이다.

정리하면

대입 비용 < 생성자 비용 + 소멸자 비용 이고 w 객체가 전체 코드에서 수행 성능에 민감하다 => 1번

대입 비용 > 생성자 비용 + 소멸자 비용 이고 w 객체가 전체 코드에서 수행 성능에 민감하지 않다 => 2번

 

이것만은 잊지 말자

변수 정의는 늦출 수 있을 때까지 늦추자. 프로그램이 더 깔끔해지며 효율도 좋아진다.

728x90