변수를 정의하면 생성자와 소멸자가 호출되는 비용은 피해갈수 없다.
사용하지 않는 변수를 정의했을 때도 당연히 비용을 지출하는데, 이런 비용은 의미없는 비용이니 피해야한다.
비밀번호가 충분히 길 경우 해당 비밀번호를 암호화하여 반환하는 함수가 있다.
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번
이것만은 잊지 말자
변수 정의는 늦출 수 있을 때까지 늦추자. 프로그램이 더 깔끔해지며 효율도 좋아진다.
'서적 정리 > Effective C++' 카테고리의 다른 글
30.인라인 함수는 미주알고주알 따져서 이해해 두자 (0) | 2021.12.19 |
---|---|
29.예외 안전성이 확보되는 그날 위해 싸우고 또 싸우자! (0) | 2021.12.19 |
28.내부에서 사용하는 객체에 대한 "핸들"을 반환하는 코드는 되도록 피하자 (0) | 2021.12.19 |
27.캐스팅은 절약, 또 절약! 잊지 말자 (0) | 2021.12.17 |
25.예외를 던지지 않는 swap에 대한 지원도 생각해 보자 (0) | 2021.12.16 |
24.타입 변환이 모든 매개변수에 대해 적용되어야 한다면 비멤버 함수를 선언하자 (0) | 2021.12.15 |
23.멤버 함수보다는 비멤버 비프렌드 함수와 더 가까워지자. (0) | 2021.12.14 |
22.데이터 멤버가 선언될 곳은 private 영역임을 명심하자 (0) | 2021.12.14 |
댓글