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

Jangmanbo·2023년 5월 31일
0

Effective C++

목록 보기
26/26

변수를 정의하면 필수로 지불하는 비용

  • 생성자, 소멸자가 있는 타입의 변수를 정의하면 변수를 정의할 때 생성자, 변수가 유효범위를 벗어날 때 소멸자를 호출하는 비용을 지불한다.
  • 변수가 정의됐으나 사용되지 않더라도 마찬가지


변수를 사용하기 전까지 변수의 정의를 늦추기

string encryptPassword(const string& password)
{
	using namespace std;
    
    string encrypted;
    if (password.length() < MinimumPasswordLength)
    {
    	throw logic_error("Password is too short");
    }
    ...		// 비밀번호를 암호화해서 encrypted 변수에 대입
    
    return encrypted;
}

encrypted는 예외가 발생한다면 사용하지 않는 변수이다. 그러나 encryptePassword 함수가 예외를 던져도 ecrypted 객체의 생성과 소멸에 대한 비용을 내야 한다.


string encryptPassword(const string& password)
{
	using namespace std;
    
    if (password.length() < MinimumPasswordLength)
    {
    	throw logic_error("Password is too short");
    }
    
    string encrypted;
    ...		// 비밀번호를 암호화해서 encrypted 변수에 대입
    
    return encrypted;
}

변수 정의를 꼭 필요하기 전까지 미루었다.

그러나 아직 해야 할 일이 남아있다. encrypted를 생성한 후 값을 대입하는데, 이는 원하는 값으로 직접 초기화하는 것보다 비효율적이다. 항목 4


변수 초기화 방법에 따른 차이

비효율적인 방법 (기본 생성자 호출 -> 대입)

string encryptPassword(const string& password)
{
	...
    
    string encrypted;	// encrypted 생성, 기본 생성자 호출
    encrypted = password;	// 대입
    
    encrypt(encrypted);	// 암호화
    return encrypted;
}

효율적인 방법 (복사 생성자 호출)

string encryptPassword(const string& password)
{
	...
    
    string encrypted(password);	// 변수 정의와 동시에 초기화, 복사 생성자 호출
    
    encrypt(encrypted);	// 암호화
    return encrypted;
}

기본 생성자를 호출한 후에 대입하는 것보다 복사 생성자를 1번 호출하는 것이 효율적이다.



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번이 방법이 효율적이다. (특히 n이 더 클수록)
그렇지 않다면 2번 방법이 효율적이다.

참고해야 할 것은 1번은 w의 유효범위가 2번보다 더 크기 때문에 유지보수 면에서 더 안좋을 수 있다.

따라서 대입이 생성자/소멸자보다 비용이 덜 들고 전체 코드에서 수행 성능에 민감한 것이 아니라면 2번 방법(루프 안에서 정의)을 쓰자!




변수 정의는 늦출 수 있는 데까지 늦추자!
1. 변수를 사용하기 전까지 변수의 정의를 늦추기
=> 사용하지 않을 객체에 대한 비용을 지불할 일이 없음
2. 가능하다면 초기화 인자를 손에 넣기 전까지 정의를 늦추기
=> 불필요한 기본 생성자 호출이 없음

0개의 댓글