2014-11-23 2 views
4

따라서 참조 초기화 양식 중 일부는 here으로 테스트했습니다. 궁금 할 때 :참조 초기화 양식

T & ref = { arg1, arg2, ... }; 

T && ref = { arg1, arg2, ... }; 

형태 적 사용과 정확히 무엇을위한 것 . 나는이 같은, 그것은 'initializer_list'로 일시적 배열과 생성자를 초기화 겠 : 이러한 맥락에서

int main() 
{ 


    struct _ab 
    { 
     _ab() {cout << "_ab()" << endl;} 

     _ab(initializer_list<int> iArr) : a(*iArr.begin()), b(*iArr.end()) {cout << "_ab()" << endl;} 

     ~_ab() {cout << "~_ab()" << endl;} 
     int a, b; 
    }; 
    const _ab & i = {1, 2}; 

    cout << i.a << endl; 

    return 0; 
} 

내가 같이 기본 생성자를 사용하여 객체 _ab '임시로 const를 참조를 초기화하려고 :

int main() 
    { 


     struct _ab 
     { 
      _ab() {cout << "_ab()" << endl;} 

      _ab(initializer_list<int> iArr) : a(*iArr.begin()), b(*iArr.end()) {cout << "_ab()" << endl;} 

      ~_ab() {cout << "~_ab()" << endl;} 
      int a, b; 
     }; 
     const _ab & i(); // error 1 

     cout << i.a << endl; // error 2 

     return 0; 
    } 
그러나이 예는이 오류와 함께 컴파일되지 않은 :

오류 1 : 'const를 :: _ AB & 난()) (주' ', 지방 유형을 사용하여 선언 const를main() :: _ ab '가 사용되지만 정의되지 않음 [-fpermissive] |

오류 2 : 비회원 유형 인 'i'에 'a'멤버를 요청하십시오. 'const main() :: _ ab &()'|

정확하게 위의 2 구문이 &을 의미하는 것을 나에게 밝힐 수 있습니까?

편집 : 두 번째 예제의 문제점을 이해합니다. 변수 대신 함수를 선언하고있었습니다. 하지만 여전히 누군가가 참조가 초기화 목록으로 초기화 될 가능성과 사용 된 이유에 대해 설명 할 수 있습니까? 그 첫 번째 오류입니다 - 코드 위

+0

답변을 수정했습니다. –

+0

접두어로,'_ab'는 타입에 대한 이상한 이름입니다.'ab'는 무엇이 잘못 되었습니까? –

답변

4
const _ab & i(); 

기준은 [dcl.init]에서 음이 설명/8

[참고 : () 이후가 초기화에 대한 구문에 의해 허용되지 않습니다,

X a(); 

클래스 X의 객체의 선언하지만, 함수의 선언 더 인수를 복용하지하고 X을 반환하지 않습니다.

이것은 유형에 관계없이 적용되며 가장 번거로운 구문 분석이라고합니다. 물론 i.a은 부적절합니다. 참조가 가능 초기화리스트로 초기화하고 사용 무엇을해야 할 이유


하지만 여전히 누군가 나를 설명 할 수 있습니까?

[dcl.init]/3 다음과 같이 목적이나 종류 T의 기준

리스트 초기화 정의된다

  • [...]

  • 그렇지 않으면 이니셜 라이저 목록에 E 유형의 단일 요소가 있고 T가 참조 유형이 아니거나 참조 된 유형이인 경우참조 관련 : E, 개체 또는 참조가 해당 요소에서 으로 초기화됩니다. 축소 변환 (아래 참조)이 으로 요소를 T로 변환해야하는 경우 프로그램이 잘못 작성됩니다. T가 참조 형식 인 경우

  • 그렇지 않으면, T에 의해 참조되는 유형의 prvalue 일시적으로 복사 목록 초기화 또는 에 대한 초기화의 종류 기준에 따라 직접 목록 초기화 , 그리고이다 참조는 그 임시에 바인딩됩니다.
    [참고 : 평소와 마찬가지로 참조 유형이 비 const 유형에 대한 값이있는 참조 인 경우 바인딩이 실패하고 프로그램이 잘못 작성됩니다.- 엔드 노트는]

마지막 주

int& i = {1}; 

우리가 const가 아닌 좌변 기준에 1을 결합해야하기 때문에 잘못 형성되어 있다는 사실을 의미하는 불가능합니다. 어느 쪽도하지 않습니다

std::string& s = {20, '5'}; 

유효하지 않은 시가 좌 표값을 임시로 초기화해야하기 때문에 유효하지 않습니다.

struct S { 
    S(std::initializer_list<double>); // #1 
    S(const std::string&);   // #2 
    // ... 
}; 

const S& r1 = { 1, 2, 3.0 }; // OK: invoke #1 
const S& r2 { "Spinach" };  // OK: invoke #2 
S& r3 = { 1, 2, 3 };   // error: initializer is not an lvalue 
const int& i1 = { 1 };   // OK 
const int& i2 = { 1.1 };  // error: narrowing 
const int (&iar)[2] = { 1, 2 }; // OK: iar is bound to temporary array 

이것은 또한 함수 호출에 특히 유용 할 수 있습니다 :
표준은 다음 예제를 제공합니다.

3

const _ab & i();

(및 통화) 구조체를 _ab하는 const를 참조를 반환하는 기능를 선언합니다. 두 번째 오류는 함수의 멤버 변수에 액세스하려고 시도하는 것이므로 (i) 불가능합니다.

가 새 {...} C++ (11) 구문을 사용할 수있는 기본 생성자를 사용하려면, 당신의 예에서 작동합니다

const _ab & i {}; // probably will work fine 

그러나 오류로 이어질 것 중괄호 omiting -이 하나가 작동하지 않습니다

const _ab & i; // error 

이 또한 잘 작동합니다 :

const _ab & i = {}; 

편집 :

참조가 "const"인 경우에만 "익명"개체 (모든 예제에서와 같이)로 참조를 초기화 할 수 있습니다. 언어로 허용 되었기 때문에 더 깊은 이유가 있고 왜 허용되어서는 안되는지 확실하지 않습니다. 그래서 당신은 실제로 이니셜 라이저 목록 (또는 무엇이든)을 사용하여 참조를 초기화하지 않습니다. 이것들은 익명 객체를 초기화하는 데 사용되며,이 익명 객체는 const 참조의 "대상"으로 사용됩니다.당신이 explicit을 할 생성자를 선언 싶다면 유형을 지정해야하는 것, 그래서 아마 그 경우에는 초기화가 실제로 사용되는지에 관해서는 혼란되지 않을 것 :

const _ab & i = _ab{/*...*/}; 

이가 당량 :

const _ab anonymousObject = _ab{/*...*/}; 
const _ab & i = anonymousObject; 
+0

그래서 실제로 참조를 초기화하는 초기화 목록 양식을 사용하여 임시 객체를 만드는 데 사용됩니다. – AnArrayOfFunctions

+0

@Jako - 정확하게 –

0

표시되는 내용은 rvalue를 const 참조로 바인딩 할 수있는 경우와 유사합니다.

std::string str() { return "blah"; } 

const std::string& s = str(); 

함수에서 반환 한 prvalue는 참조에 바인딩되며 참조 수명이 끝날 때까지 연장됩니다.

또 다른 방법

은 직접 임시 객체를 생성하여 같은 규칙이 운동하기 : 이것은 (참조의 수명에 대한 수명 연장) 기준에 바인딩되는 임시을 생성

const std::string& s = std::string(); 

.

const _ab& i = {1, 2}의 경우와 매우 유사하지만,이 비슷 즉 보강-초기화 목록에서 건설되고 유형 _ab의 암시 일시에 의존 :

const _ab& i = _ab{1, 2}; 

(차이는 처음이다 양식은 _ab의 initializer_list 생성자가 explicit인데 반해 두 번째 것은 명시 적 생성자에 대해서도 작동하지만 ... 이니셜 라이저 목록 생성자 explicit은 어렵고 혼란 스럽기 때문에 피해야합니다. 객체 초기화).

이 구문은 참조를 사용하는 대신 보통 const _ab{1, 2};으로 작성하기 때문에 위에서 설명한대로 정확하게 유용하지는 않습니다. 그러나 const-reference를 취하는 함수를 호출 할 때 braced-init-list를 사용하여 인수를 초기화하는 것이 유용합니다. std::pair<int, const char*>을 취하는 함수는 func({1, "two"})이라고 부를 수 있습니다. 이는 C++ 03에 해당하는 것보다 더 편리합니다 : func(std::make_pair(1, "two")). 이를 작동 시키려면 참조 목록을 초기화하여 임시의 암시 적 생성을 야기 할 수 있어야하며, 이는 사용자가 묻는 const _ab& = {1, 2} 양식으로 연결됩니다.