성공할 게임개발자

[Effective c++] [5. 구현] 26. 변수 정의는 늦출 수 있는 데까지 늦추는 근성을 발휘하자 본문

C++

[Effective c++] [5. 구현] 26. 변수 정의는 늦출 수 있는 데까지 늦추는 근성을 발휘하자

fn000 2025. 6. 8. 12:14

변수를 앞서서 정의하면 수행 성능이 떨어진다.

 

생성자 소멸자를 끌고 다니는 타입으로 변수를 정의하면 각각 생성할 때, 소멸할 때 호출 비용이 발생한다. 이는 정의되어 사용되지 않아도 비용이 부과된다

 

std::string encryptPassword(const std::string& password)
{
    using namespace std;
 
    string encrypted;
 
    if(password.length() < MinimumPasswordLength)
    {
        throw logic_error("Password is too short");
    }
 
    ...             // 주어진 비밀번호를 암호화하여 encrypted 
    				// 변수에 넣는 데 필요한 일들을 여기서 한다.
 
    return encrypted;
}

이 코드 설계의 경우 encrypted 객체가 이 함수에서 안쓰이진 않지만 예외가 발생하면 이 변수는 사용하지 않는다. 즉, 예외가 터져도 객체 생성과 소멸에 대한 비용을 내야한다.

 

 

 

std::string encryptPassword(const std::string& password)
{
    using namespace std;
 
    if(password.length() < MinimumPasswordLength)
    {
        throw logic_error("Password is too short");
    }
 
    string encrypted;	//정의를 예외 뒤로
 
    ...              // 주어진 비밀번호를 암호화하여 encrypted 
    				// 변수에 넣는 데 필요한 일들을 여기서 한다.
 
    return encrypted;
}

 

객체가 생성되고 가장 먼저하는 일이 생성자에 값을 주는 일이다. 하지만 string encrypted 변수가 정의될 때 초기화 인자가 없다.

객체를 생성하고 그 후 값을 대입하는 방법은 직접 초기화하는 방법보다 효율이 좋지 않다. (항목4 : 객체를 사용하기 전에 객체를 초기화하자)

 

 

 

따라서 다음의 코드처럼 string encrypted를 password로 복사생성자를 통해 초기화한다. 초기화 인자를 손에 넣기 전까지 정의는 늦출 수 있는지 둘러봐야 한다.

std::string encryptPassword(const std::string& password)
{
	... 	//길이를 점검
    std::string encrypted(password);		//변수를 정의함과 동시에 초기화(복생)
    
    encrypt(encrypted);
    return encrypted;
}

이번 항목의 제목 "늦출 수 있는 데까지"의 뜻이 이것이다.

 

 

 

 

루프에 대해서는 어떨까? 어떤 변수가 루프 안에서만 쓰인다면 해당 변수를 루프 바깥에서 미리 정의하고 루프에서 대입하는게 좋을까 루프 안에서 변수를 정의하는 방법이 좋을까?

 

 

A 방법 : 루프 바깥쪽에서 정의

Widget w;
for(int  i = 0; i < n; ++i)
{
    w = i에 따라 달라지는 값;
    ...
}

 

 

B방법 : 루프 안쪽에서 정의

for(int  i = 0; i < n; ++i)
{
    Widget w(i에 따라 달라지는 값);
    ...
}

 

 

 

A 방법은 보다싶이 생성자 1번 + 소멸자 1번 + 대입 n번

B 방법은 생성자 n번 + 소멸자 n번

 

 

클래스 중에는 대입에 들어가는 비용이 생성, 소멸보다 적은 경우가 있는데, Widget이 그렇다면 A를 선택해야 한다. 반대면 B를 선택해야한다. 

 

하지만 생각해볼 부분이 하나 더 있다. A방법을 쓰면 w라는 이름을 볼 수 있는 유효범위가 B방법을 쓸 때보다 넓어지기 때문에(루프를 포함하는 유효범위) 프로그램 이해도와 유지보수성이 역으로 안 좋아진다.

 

따라서 아래의 방법대로 한다.

대입이 생성, 소멸자 보다 비용이 덜 들고 전체 코드에서 수행성능에 민감한 부분을 건드리지 않는다면 그냥 B방법이 좋다.

 

 

 

중요포인트!

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