언어/Effective C++

[Effective C++] #26_변수 정의는 늦출 수 있는 데까지 늦추는 근성을 발휘하자

Hardii2 2021. 12. 27. 10:21

[Effective C++] #26_변수 정의

 

Scott Meyers의 "Effective C++" 를 통해, C++ 구현에 필요한 개념들을 이해하고, 기록하기 위함입니다. 항목은 5장 '구현', 항목 26 "변수 정의는 늦출 수 있는 데까지 늦추는 근성을 발휘"에 해당하는 내용입니다.

 


 

 

변수 정의

변수를 정의하면 항상 부담해야 하는 비용이 두 가지가 있습니다. 하나는 프로그램 제어 흐름이 변수의 정의에 닿을 때 생성자가 호출되는 비용, 또 하나는 변수가 유효범위를 벗어날 때 소멸자가 호출되는 비용입니다. 

 

 

변수를 일찍 정의 했을 때
std::string encryptPassword(const std::string& password){
	using namespace std;
    
    string encryptedPassword;
    
    if(password.length() < MinPasswordLength){		// 패스워드가 너무 짧으면 예외 발생!
    	throw logic_error("Password is too short!");
    }
    ...							// 암호화 진행
    return encryptedPassword
}

비밀번호를 암호화하는 "encryptPassword"함수 예제입니다. 이 함수는 주어진 비밀번호가 너무 짧으면 logic_error타입의 예외를 던지도록 설계되어 있습니다. "encryptedPassword" 객체가 아예 안쓰인다고 볼 수 없지만, 이 함수가 예외를 던지면사용하지 않을 "encryptedPassword" 객체의 생성과 소멸에 대해 비용을 내야 하겠죠? 따라서, 우리는 위 코드를 수정해보도록 합니다. 최대한 정의를 늦추는거죠

 

변수 생성 후 대입
std::string encryptPassword(const std::string& password){
	...
    std::string encryptedPassword;	// 최대한 정의를 늦추고
    encrytpedPassword = password;	// 대입 연산 
    
    encrypt(encryptedPassword);
    return encryptedPassword;
}

"encryptedPassword" 객체의 생성을 최대한 늦췄지만, 문제점이 한개 또 존재합니다. 객체를 기본 생성하고나서 값을 대입하는 방법보다, 우리는 객체를 원하는 값으로 직접 초기화 하는 방법이 좋다는것을 알고 있습니다. 의미없는 기본 생성자 호출을 생략하고 아래 코드로 넘어거가겠습니다.

 

직접 초기화
std::string encryptPassword(const std::string& password){
	...
    std::string encryptedPassword = encrypt(password);	
    return encryptedPassword;
}

 

루프 안에 변수를 정의? 루프 밖에 변수를 정의?
// 1. 루프 안에 정의
for(int i=0; i<n; i++){
	A a(i);
    ...
}

// 2. 루프 밖에 정의
A a;
for (int i=0; i<n i++){
	a = i;
}

2번 방법이 효율적인 경우는 클래스 중 "대입"에 들어가는 비용이 생성자+소멸자 비용보다 적게 나오는 경우입니다. 반면에 1번 방법은 대입이 생성자+소멸자 비용보다 적고, 전체 코드에서 수행성능에 민감한 부분을 건드리는 경우입니다.

 

 

 

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