본문 바로가기
서적 정리/Effective C++

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

by 민돌이2 2021. 12. 17.

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

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

 

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

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

댓글