아래는 “이번 주의 팁 #107: 참조 수명 확장”에 대한 한글 번역입니다:
제목: “이번 주의 팁 #107: 참조 수명 확장”
원문 게시일: 2015년 12월 10일
작성자: Titus Winters (titus@google.com)
개요
TotW #101 이후로 참조와 수명에 대한 혼란이 보고되었습니다. 이 팁에서는 다음 질문에 대해 자세히 알아보겠습니다:
“참조 수명 확장은 언제 적용되나요?”
string Foo::GetName();
const string& name = obj.GetName(); // 이 코드는 안전할까요? 합법적일까요?
간단히 말해, 임시 객체(참조 대상)의 수명은 다음 조건에서만 연장됩니다:
- 지역 변수
const T&
또는T&&
이 임시T
를 반환하는 표현식의 결과로 초기화되거나, - 임시 객체의
T
하위 객체(예: 구조체의 멤버 변수)를 참조할 때.
(Google 스타일에서는 주로 T&&
는 무시합니다.)
표준 문서는 다소 복잡할 수 있으므로, 몇 가지 경계 사례를 통해 이를 명확히 설명하겠습니다.
수명 확장의 적용 사례와 예외
T&
에는 적용되지 않습니다. 반드시const T&
이어야 합니다.T&
로 초기화하려 하면 컴파일 오류가 발생합니다.
- 형 변환이 있는 경우에는 수명 확장이 작동하지 않습니다.
- 예를 들어,
string
을const absl::string_view&
로 할당하면string
의 수명이 연장되지 않습니다. - 참고로
const absl::string_view&
는 사용하지 않는 것이 좋습니다.
- 예를 들어,
- 간접적으로 하위 객체를 얻는 경우 수명 확장이 작동하지 않습니다.
- 컴파일러는 함수 호출(예: getter)을 통해 간접적으로 반환된 객체를 추적하지 않습니다.
- 수명 확장은 표현식에서 반환된 임시 객체의 직접적인 멤버 변수에만 작동합니다.
- 형 변환이 허용되는 경우는 부모 클래스와 자식 클래스 간의 관계가 있는 경우뿐입니다.
- 예를 들어, 부모 클래스
T
와 자식 클래스U
가 있을 때, 자식 클래스U
의 임시 객체를 부모 클래스T&
로 참조할 수 있습니다. 하지만 이런 경우는 혼란을 초래할 수 있으므로 권장하지 않습니다.
- 예를 들어, 부모 클래스
수명 확장의 작동 방식
- 수명이 연장된 임시 객체는 참조 변수가 스코프를 벗어날 때까지 유지됩니다.
- 수명이 연장되지 않는 경우, 임시 객체는 문장의 끝(다음 세미콜론
;
)에서 파괴됩니다.
권장 사항
TotW #101에서 설명했듯이, 참조 초기화에서 수명 확장에 의존하는 것은 바람직하지 않습니다. 이는 유지보수성과 리뷰 과정에서 문제가 될 수 있습니다.
하지만, 수명 확장이 필요한 경우가 있습니다:
- 임시 컨테이너에 대한 범위 기반 for 루프와 같은 사례입니다.
- 그러나 이 경우에도, 확장은 임시 객체 전체에만 적용되며 하위 표현식에는 적용되지 않습니다.
다음은 올바르게 작동하는 예입니다:
std::vector<int> GetInts();
for (int i : GetInts()) { } // 벡터의 수명 확장이 중요합니다.
// 문자열을 각 문자(char) 단위로 분리하여 string_view로 반환합니다.
std::vector<absl::string_view> Explode(const string& s);
// 벡터의 수명은 연장되지만, 임시 문자열의 수명은 연장되지 않습니다.
for (absl::string_view s : Explode(StrCat("oo", "ps"))) { } // 잘못된 코드
다음은 수명 확장이 작동하지 않는 예입니다:
MyProto GetProto();
// MyProto가 스코프를 벗어나면서 sub_protos도 파괴됩니다.
// 컴파일러는 sub_protos()가 하위 객체를 반환하는 것을 추적하지 못합니다.
for (const SubProto& p : GetProto().sub_protos()) { } // 잘못된 코드
결론
- 수명 확장은 임시 객체의 직접 반환된 결과에만 적용됩니다.
- 형 변환이나 간접적인 하위 객체 참조에는 적용되지 않습니다.
가능하면 수명 확장에 의존하지 말고, 코드를 명시적으로 작성해 유지보수성과 가독성을 향상시키세요.