프로그래밍C++ 개발자

C++에서 객체의 직접 초기화와 간접 초기화의 차이점은 무엇이며, 내장형 및 사용자 정의 유형을 사용할 때 어떤 결과가 있을 수 있습니까?

Hintsage AI 어시스턴트로 면접 통과

답변

C++에서 객체의 직접(direct) 및 간접(copy) 초기화를 구분합니다:

  • 직접 초기화:

    MyClass obj(arg1, arg2); int x(5);

    클래스의 경우 적절한 생성자를 직접 호출합니다.

  • 간접 초기화:

    MyClass obj = MyClass(arg1, arg2); int x = 5;

    이는 임시 객체를 생성한 다음 이를 복사(또는 이동)합니다(복사 생성자/이동 생성자를 사용).

차이점:

  1. 내장형 타입에 대해 동작이 동일합니다. 클래스의 경우 호출되는 생성자의 집합이 다를 수 있거나 초기화가 금지될 수 있습니다.
  2. 생성자 요구 사항으로 인해 멤버 초기화 목록이 다양한 초기화 방법에 대해 항상 동 equivalente가 아닙니다.
  3. Copy elision(불필요한 복사를 제거하는 컴파일러 최적화)은 차이를 무효화하는 경우가 많습니다(하지만 항상 그렇지는 않으며, 특히 C++17 이전).

예제:

struct NonCopyable { NonCopyable(int) {} NonCopyable(const NonCopyable&) = delete; }; NonCopyable a(5); // OK: 직접 NonCopyable b = NonCopyable(5); // 최적화 시 OK, C++17 이전에는 오류 NonCopyable c = 5; // 오류: 복사 생성자가 없음

함정 질문

"C++11을 사용하고 최적화된 컴파일러가 켜져 있다면, copy-initialization이 direct-initialization보다 더 많은 생성자 호출을 일으킬 수 있습니까?"

답변: 이론적으로는 가능합니다. copy elision이 없으면 copy-initialization은 임시 객체를 생성하고, 이후 복사 생성자 또는 이동 생성자를 호출합니다. Direct-initialization은 항상 기본 생성자만 호출합니다. 그러나 현대 컴파일러는 최적화가 활성화되어 있을 경우(예: C++17 이상) guaranteed copy elision을 통해 이러한 차이를 제거합니다.

주제의 미세한 부분을 알지 못해 발생한 실제 오류 사례


이야기

금융 프로젝트에서 임시 객체와 함께 copy-initialization을 사용했지만 필요한 타입에 복사 생성자가 없었습니다. 애플리케이션은 오래된 컴파일러(C++17 이전)에서는 컴파일되지 않았지만 direct-init은 작동했습니다.


이야기

데이터 직렬화 유틸리티에서 프로그래머들은 direct-init과 copy-init이 동등하다고 생각했습니다. 결과적으로 대형 구조체의 불필요한 복사와 성능 저하가 발생했습니다.


이야기

사용자 정의 객체의 전역 배열 초기화 시 간접 초기화를 사용했습니다. 오류는 copy elision이 발생하지 않는 단일 플랫폼에서만 나타났고, ABI의 특성으로 인해 불필요한 생성자의 암시적 호출이 발생했습니다.