2011-07-26 2 views
13

참고 : g ++ 컴파일러를 사용하고 있습니다. (나는 꽤 잘 듣고 표준에 꽤 가깝습니다.)Ints의 배열에 대한 참조를 선언 할 때 왜 const 포인터에 대한 참조가되어야합니까?


의 당신이 int 배열 선언 한 가정 해 봅시다 :

int a[3] = { 4, 5, 6 }; 
이제

의 당신이 정말 배열 (신경 끄시 고, 왜 다른 비얀보다 참조를 선언하고 싶은 말은하자 언어가 지원 말한다).

다음
int*& ra = a; 

컴파일러 balks을 다음과 같이 말한다 : -

사례 1은 당신이하려고하면 처음

"invalid initialization of non-const reference of type `int*&' from a temporary of type `int*'" 

먼저 일을, 왜 'A'임시 변수 (예하지 않습니다이다) ...

어쨌든, 난 const가 아닌 에러를 볼 때마다, 나는 const를 던지려고 노력한다.

사례 2 - 당신이 시도하는 경우는 :

int*const&rca = a; //wish I knew where the spaces should go (but my other post asking about this sort of protocol got a negative rank while many of the answers got ranked highly -- aha! there are stupid questions!) 

그런 다음 모든 것을, 그것은 멋진 컴파일, 당신은 배열에 대한 참조를 가져옵니다.

int* justSomeIntPointer = a; //LINE 1 
int*& rpa = justSomeIntPointer; //LINE 2 

이 또한 당신에게 원래의 배열에 대한 참조를 제공합니다 : -

사례 3 지금 여기에 컴파일 다른 것입니다.

그래서 여기 내 질문 : 어느 시점에서 정적으로 선언 된 배열 의 이름은 const 포인터가됩니까? int 배열의 이름이 int에 대한 포인터라는 것을 기억하고있는 것 같습니다. 그러나 const 포인터를 int 형으로 기억하지 못했습니다 ...

Case 1처럼 보입니다. 선언 된 참조가 상수 포인터가 아니기 때문에 실패합니다. 이는 'a'가 이미 상수 포인터로 시작되었음을 의미 할 수 있습니다.

선언 된 참조 (rca)가 이미 const-pointer-to-int이기 때문에 Case 2가 작동하는 것처럼 보입니다.

사례 3도 효과가 있지만 깔끔한 이유는 무엇입니까? 상정 포인터 -to-int (즉, 배열 이름 'a')는 언제 const 포인터가됩니까? int * (LINE 1)에 할당하거나 int * & (LINE 2)에 해당 int *를 할당 할 때 발생합니까?

희망이 있습니다. 감사.

답변

27
int*& ra = a; 

int*는 포인터 타입이 아닌 배열 형식입니다. 그렇기 때문에 int[3] 유형의 a에 바인딩되지 않습니다.

int* const& ra = a; 

작품이

입니다
int* const& ra = (int*)a; 

에 해당하기 때문에이 임시 포인터는 개념적으로 할당의 오른쪽에 생성되며이 임시은 ra에 바인딩됩니다. 그래서 결국,이보다 더 낫다 :

ra 사실 배열의 첫 번째 요소가 아닌 배열에 대한 참조에 대한 포인터입니다
int* ra = a; 

.

어레이에 대한 레퍼런스를 쉬운 방법 선언 :

typedef int array_type[3]; 
array_type& ra = a; 

하지로서의 쉬운 방법 :

int (&ra)[3] = a; 

는 C++ 11 쉬운 방법 :

auto& ra = a; 

정적으로 선언 된 배열의 이름은 어느 시점에서 const 포인터가됩니까? int 배열의 이름이 int에 대한 포인터라는 사실을 기억하는 것 같습니다. 그러나 const 포인터를 int 형으로 기억하지 못했습니다.

물어볼 올바른 질문! 배열 - 포인터 붕괴가 발생하면 이해한다면 안전합니다. '복사'어떤 종류의 시도 될 때

  • 부패가 변환의 종류와 수 (C는 배열을 직접 복사 할 수 없기 때문에)

    • 붕괴가 발생합니다 간단하게 고려해야 할 두 가지가 있습니다 넣어 형식이 일치하지 않을 때 언제든지 변환이 가능합니다.

    첫 번째 종류는 일반적으로 템플릿에서 발생합니다. . 유형 int[3]의 배열에 복사 할 수 없기 때문에 그래서 template<typename T> pass_by_value(T); 주어진 다음 pass_by_value(a) 실제로 int*을 전달합니다

    을 두 번째에 관해서는, 당신은 이미 행동을 본 적이 :이 두 번째 경우에 발생 int* const&int[3]에 바인딩 할 수 없지만 임시로 int*에 바인딩 할 수 있으므로 변환이 발생합니다.

  • -2

    a는 malloc 또는 new를 사용하여 스택에 선언했기 때문에 임시 변수입니다.

    +0

    그래서 임시 변수는 항상에서 const됩니다

    이 배열에 대한 참조입니다? – Jimmy

    +3

    @Jimmy : 임시 변수가 항상 const는 아니지만 언어가 비 const 참조에 직접 바인딩하는 것을 금지합니다. 배열'a'는 일시적이지 않습니다. 그러나 임시적인 배열 대 포인터 변환으로 인한 포인터입니다. –

    +0

    스택에 선언되어있는 것은 '자동 저장 기간 보유'를 의미합니다. 즉, 포함 된 블록/오브젝트가 '임시'가 아닌 범위에서 벗어납니다. 플러스 포인트가되도록 동적으로 할당 된 객체를 수동으로 관리해야하는 경우는 거의 없습니다. 마지막으로 필요한 것은 동적 할당이 더 좋은 이유에 대한 잘못된 생각입니다. 이것은 매우 잘 정의되고 다른 의미를 지닌 용어 인 _temporary_의 잘못된 정의를 호출하기 때문에 특히 나쁩니다. –

    0

    정적으로 선언 된 배열의 이름은 언제 점이 const 포인터가됩니까? int 배열의 이름이 int에 대한 포인터라는 사실을 기억하고있는 것 같습니다. 그러나 const 포인터를 int 형으로 기억하지 못했습니다.

    값은 cpp 파일에 있습니다. 이것이 상수입니다.

    당신은 사용할 수 있습니다

    const int *pToArray = a; 
    

    또는

    const int *pToArray = (const int*)&a[0]; 
    
    2

    대부분의 사람들이 생각하는 매우 큰 실수 (아주 좋은 인터뷰 질문)는 배열의 이름이 포인터와 같다고 생각한다는 것입니다. 그건 사실이 아니야. 이 실수로 인해 C 프로그램에서 버그를 연결하는 많은 버그가 발생하며 디버그하기가 매우 어렵습니다. diffrence는 다음과 같습니다. 배열의 이름은 구조체의 첫 번째 요소 인 배열입니다. 배열 이름의 유형은 그러나 포인터 유형이 아니라 배열 유형입니다. 반면에 포인터는 다른 정보가없는 한 가지에 대한 포인터 일뿐입니다. 포인터 유형은 포인터 유형입니다. arraytype은 스택에 있는지 없는지 알고있는 것과 같은 다른 속성을 가지고 있습니다. 따라서 "임시". 귀하의 경우 임시 오류는 임시 변수가 참조에 지정되지 못하게하는 검사에서 비롯됩니다. const 키워드는 체크를 끕니다. 반면에 포인터 유형에는 "임시"라는 개념이 없습니다. 이제 컴파일러를 속여서 스택에있는 무언가에 대한 참조를 할당하려고한다고 가정합니다. 이 경우 포인터로 만들어야합니다. 방법?

    int * &aa = & a [0];

    위의 경우 먼저 값을 얻고 & (연산자 주소)을 사용하여 pointerType을 만듭니다. 이제 포인터 유형은 스택 (임시 변수)에 있는지 여부에 대한 정보가 없습니다. 그러나 이것은 배열의 첫 번째 요소에 대한 포인터를 참조합니다. (따라서 단지 포인터 타입이 아닌 ArrayType를)

    1

    당신이 정말로 배열에 대한 참조를 원한다면, 당신은 다음 사용해야합니다

    int a[3] = { 4, 5, 6 }; 
    int (&ra)[3] = a; 
    

    int *&로 만들려고하는 것은 참조입니다 int에 대한 포인터. 이것은 같은 유형이 아닙니다. 그리고 변경할 수없는 값으로 참조를 초기화하면 (배열의 주소) 포인터 const (int가 아님)를 선언해야합니다. 지금이 라인

    int a[3] = { 4, 5, 6 }; 
    

    :

    int*& ra = a; 
    

    포인터에 대한 참조를 만듭니다

    1

    당신은 int 배열을 가지고있다. 임시 포인터 (a 배열에서 변환)를 만들면 표준에서 임시 참조를 참조로 할당 할 수 없으므로 컴파일러는 불평합니다.

    int *pa = a; 
    int *& rpa = pa; 
    

    상수 참조 임시직에 대한 참조를 보유 할 수 있지만, 당신은 이미 그것을 발견 :

    그래서, 그것을 해결하기 위해, 당신은 포인터를 만든 다음 포인터에 대한 참조에 할당해야합니다.

    template< typename T, size_t N > 
    size_t ArraySize(T (&)[ N ]) 
    { 
        return N; 
    } 
    

    이 기능은 배열에 대한 참조를 받아,이 크기의 반환 - 당신이 (배열 참조에 대해) 물어 무엇

    배열에 대한 참조를 만드는 방법에 대한 가장 유명한 예는 이것이다.

    8

    C++의 단어 "array"는 대괄호 []으로 표기됩니다. C++에서 something-array-something을 선언하려면 선언에 대괄호가 있어야합니다. 대신 별표 *을 쓰면 포인터가 생깁니다.포인터와 배열은 서로 다른 두 가지입니다.

    int (&ra) [3] = a; 
    
    관련 문제