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

업데이트:     Updated:

카테고리:

태그:

이 글은 아래의 책을 자세히 정리한 후, 정리한 글을 GPT에게 요약을 요청하여 작성되었습니다.
이펙티브 C++ 제3판, 스콧 마이어스 저자, 곽용재 번역

📦 5. 구현

👉🏻 항목 26: 변수 정의는 늦출 수 있는 데까지 늦추는 근성을 발휘하자

변수를 정의할 때는 두 가지 비용이 발생한다.

1. 변수 정의 시점에 생성자가 호출되는 비용
2. 유효범위를 벗어날 때 소멸자가 호출되는 비용

게다가 정의만 해놓고 사용하지 않더라도 비용은 그대로 발생한다.

예제를 보며 살펴보자.


✅ 불필요한 생성 방지

string encryptPassword(const string& password) {
	string encrypted;

	if(password.length() < MinimumPasswordLength) {
		throw logic_error("Password is too short");
	}
	...

	return encrypted;
}

위 코드에선 encrypted가 먼저 생성되고, 조건에 의해 예외가 발생하면 쓸모없는 객체가 만들어진다.

이번엔 다음 코드를 살펴보자:

string encryptPassword(const string& password) {
	if(password.length() < MinimumPasswordLength) {
		throw logic_error("Password is too short");
	}

	string encrypted; // 기본 생성자 호출
	encrypted = password; // 대입 연산자 호출
	...
	return encrypted;
}

이 경우에도, 생성 후에 또 대입이 일어난다.

좀 더 낫게 작성하면 이렇게 된다:

string encryptPassword(const string& password) {
	if(password.length() < MinimumPasswordLength) {
		throw logic_error("Password is too short");
	}

	string encrypted(password); // 정의와 동시에 초기화
	...
	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번 X


✅ A 방법

  • 생성/소멸은 1번씩만 일어나고, 대입이 n번 발생
  • 단점: 변수의 유효 범위가 루프 외부까지 넓어짐 → 유지보수성 저하

✅ B 방법

  • 루프마다 생성/소멸이 발생
  • 대입이 없고, 유효 범위가 루프 내부로 한정

🧐 언제 어떤 방법을?

A vs B는 상황에 따라 결정하면 된다.

특히 B 방법은 아래 조건이라면 유리하다:

  • 대입 연산 비용이 생성자+소멸자 비용보다 크다
  • 성능에 민감한 코드

🧐 정리

  • 변수 정의는 늦출 수 있을 때까지 늦추자.
    → 코드가 깔끔해지고, 효율도 높아진다.
  • 루프 안에서도 필요하다면 범위를 좁히고 대입을 피하자.
    → 유지보수성도 좋아진다.

Cpp 카테고리 내 다른 글 보러가기

댓글남기기