C ++ 11에서“return {}”문은 무엇을 의미합니까?


115

진술은 무엇입니까

return {};

C ++ 11에서는 (말하자면) 대신 사용할 때를 나타냅니다.

return NULL;

또는

return nullptr;

59
함수의 반환 유형의 기본 생성 인스턴스를 반환합니다.
리처드 스

아니면 return;가치 가 없는 단순한 가요?
i486

아니요, 토론에서 알 수 있듯이 함수가 무언가를 반환해야하고 (즉, void 반환 유형이 아님) 그냥 작성하면 컴파일 타임 오류입니다. return; 반면 return{};에 반환 유형이 있으면 유효합니다.
Pedia

@Pedia 항상 그런 것은 아닙니다. 일부 개체는 구성에 인수가 필요합니다
MM

답변:


108

return {};"빈 목록 초기화 프로그램으로 초기화 된 함수의 반환 유형 객체 반환"을 나타냅니다 . 정확한 동작은 반환 된 객체의 유형에 따라 다릅니다.

에서 cppreference.com을 합니다 (영업 이익 + 11 C 태그 때문에, 나는 C ++ 14과 C ++ (17)의 규칙을 제외, 더 자세한 사항은 링크를 참조)

  • braced-init-list가 비어 있고 T가 기본 생성자가있는 클래스 유형이면 값 초기화가 수행됩니다.
  • 그렇지 않고 T가 집계 유형이면 집계 초기화가 수행됩니다.
  • 그렇지 않고 T가 std :: initializer_list의 전문화이면 T 객체는 컨텍스트에 따라 braced-init-list에서 직접 초기화되거나 복사 초기화됩니다.
  • 그렇지 않으면 T의 생성자가 두 단계로 고려됩니다.

    • std :: initializer_list를 유일한 인수로 사용하거나 나머지 인수에 기본값이있는 경우 첫 번째 인수로 사용하는 모든 생성자는 std :: initializer_list 유형의 단일 인수에 대해 오버로드 확인에 의해 검사되고 일치됩니다.
    • 이전 단계에서 일치 항목이 생성되지 않으면 T의 모든 생성자가 중괄호 초기화 목록의 요소로 구성된 인수 집합에 대한 오버로드 확인에 참여하며 비 좁히기 변환 만 허용된다는 제한이 있습니다. 이 단계가 명시 적 생성자를 복사 목록 초기화에 가장 적합한 것으로 생성하면 컴파일이 실패합니다 (단순 복사 초기화에서는 명시 적 생성자가 전혀 고려되지 않음).
  • 그렇지 않으면 (T가 클래스 유형이 아닌 경우), 중괄호 초기화 목록에 하나의 요소 만 있고 T가 참조 유형이 아니거나 요소 유형과 호환되는 참조 유형 인 경우 T는 직접적입니다. 축소 변환이 허용되지 않는 경우를 제외하고 초기화 (직접 목록 초기화) 또는 복사 초기화 (복사 목록 초기화)

  • 그렇지 않으면 T가 요소의 유형과 호환되지 않는 참조 유형 인 경우. (참조가 상수가 아닌 lvalue 참조 인 경우 실패 함)
  • 그렇지 않고 braced-init-list에 요소가 없으면 T는 값이 초기화됩니다.

C ++ 11 이전에는를 반환하는 함수에 대해 다음 std::string과 같이 작성했을 것입니다.

std::string get_string() {
    return std::string();
}

C ++ 11에서 중괄호 구문을 사용하면 유형을 반복 할 필요가 없습니다.

std::string get_string() {
    return {}; // an empty string is returned
}

return NULL그리고 return nullptr함수 포인터 타입을 반환 할 때 사용되어야한다 :

any_type* get_pointer() {
    return nullptr;
}

그러나 NULL는 정수 값 (0)에 대한 별칭 일 뿐이며 nullptr실제 포인터 유형 이므로 C ++ 11부터 사용되지 않습니다 .

int get_int() {
    return NULL; // will compile, NULL is an integer
}

int get_int() {
    return nullptr; // error: nullptr is not an integer
}

91

이것은 아마도 혼란 스러울 것입니다.

int foo()
{
  return {};   // honestly, just return 0 - it's clearer
}

이것은 아마도 아닙니다 :

SomeObjectWithADefaultConstructor foo()
{
  return {};
  // equivalent to return SomeObjectWithADefaultConstructor {};
}

9
따라서 반환 유형에 기본 생성자가 없으면 컴파일 타임 오류입니다.
피디아

10
반환 유형이 비명 시적 기본 생성자가없고 집계가 아닌 클래스 인 경우 컴파일 오류 입니다.
Oktalist

3
유형에 initializer_list생성자가있는 경우 기본 생성자를 사용할 수 없으면 사용되지 않습니까?
celtschk

4
"아마 혼란스러워"? 이것이 이름없는 영혼이 "C ++ 인 그 부풀어 오른 음란"을 언급 한 이유일까요? 이것이 제공하는 키 입력의 저장이 제공하는 명확성이 부족할 가능성을 정당화 할 수 있습니까? 이것은 진지한 질문입니다. 실용적인 예를 들어 저를 설득 해주세요.
MickeyfAgain_BeforeExitOfSO

4
return {}동일하지 않습니다return SomeObjectWithADefaultConstructor{};
MM

26

return {};{}이것이 반환 값 의 이니셜 라이저 임을 의미합니다 . 반환 값은 빈 목록으로 목록 초기화됩니다.


다음은 C ++ 표준의 [stmt.return]을 기반 으로 한 반환 값 에 대한 배경입니다 .

값으로 반환하는 함수의 경우 (즉, 반환 유형은 참조가 아니고 참조가 아님 void) 반환 값 이라는 임시 객체가 있습니다. 이 개체는 return문에 의해 생성되며 이니셜 라이저는 return 문에있는 내용에 따라 다릅니다.

반환 값은 함수를 호출 한 코드에서 전체 표현식이 끝날 때까지 유지됩니다. 클래스 유형이있는 경우 해당 소멸자는 참조를 직접 바인딩하는 호출자가 수명을 연장하지 않는 한 실행됩니다.

반환 값은 두 가지 방법으로 초기화 할 수 있습니다.


T함수의 반환 유형 이라고 가정하면 다음 return T{};과 다른 점에 유의 return {}하십시오. 전자에서는 임시 T{}가 생성 된 다음 반환 값 이 해당 임시에서 복사 초기화됩니다.

T액세스 가능한 복사 / 이동 생성자가 없으면 컴파일에 실패 하지만 return {};해당 생성자가없는 경우에도 성공합니다. 따라서 return T{};복사 생성자 등의 부작용이 나타날 수 있지만 이는 복사 제거 컨텍스트이므로 그렇지 않을 수 있습니다.


다음 은 이니셜 라이저가 빈 목록 인 C ++ 14 (N4140 [dcl.init.list] / 3) 의 목록 초기화 에 대한 간략한 요약입니다 .

  • 경우 T집합이며, 각 부재는 초기화 할 브레이스 또는 동등 이니셜 ,이 있었다면, 그렇지 않은 경우와 같이 {} (그래서 재귀 다음 단계를 적용).
  • T사용자가 제공 한 기본 생성자가있는 클래스 유형 인 경우 해당 생성자가 호출됩니다.
  • 경우 T암시 적으로 정의하거나,와 클래스 타입 = default에드 기본 생성자는 객체는 제로가 초기화 한 후 기본 생성자가 호출됩니다.
  • 경우 TA는 std::initializer_list, 반환 값은 빈 등의 목록입니다.
  • 그렇지 않으면 (즉 T, 클래스가 아닌 유형-반환 유형은 배열이 될 수 없음) 반환 값은 0으로 초기화됩니다.

Aggregate init가 먼저 나오고 {}value-init 일 수도 있고 아닐 수도있는로 모든 멤버를 재귀 적으로 초기화 합니다.
TC

@TC 맞아, 나는 cppreference에 의해 갔지만 "까지 C ++ 14"를 간과했다
MM

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.