c++ - 타입 - 상수에 대한 포인터의 참조 해제




c++ 참조타입 (7)

object라는 클래스가 있다고 가정 해 봅시다.

int main(){
    object a;
    const object* b = &a;
    (*b); 
}

질문 : b는 const에 대한 포인터이지만 포인터가 가리키는 객체는 실제로 상수 객체가 아닙니다. 내 질문은 우리가 포인터를 역 참조 할 때 "b"는 왜 그것이 실제로 가리키고있는 객체가 아닌 상수 객체인지를 알 수있다.


간단히 말해서,

  1. 일반 poiters의 경우, 단항 연산자 * 의 결과는 pointed-to 유형에 대한 참조 입니다.

  2. 따라서 pointed-to가 const-qualified 인 경우 결과는 상수에 대한 참조 입니다.

  3. 상수에 대한 참조는 모든 객체에 바인딩 할 수 있습니다. 동일 유형의 변경 가능한 객체에도 바인딩 할 수 있습니다. constref를 값에 바인딩 할 때,이 refence를 통해 ad-hoc 값을 수정하지 않을 것을 약속한다. (여전히 const 참조가 아닌 const 참조로 캐스트 할 수있다.)

  4. 마찬가지로 const 포인터는 다른 방법으로 수정할 수있는 객체를 가리킬 수 있습니다.


그것이 왜 그런지에 대한 구체적인 예가 있습니다. 선언한다고 가정 해 보겠습니다.

int a[] = {1, 2, 3};
constexpr size_t n_a = sizeof(a)/sizeof(a[0]);

extern int sum( const int* sequence, size_t n );
sum_a = sum( a, n_a );

이제 다른 모듈에 sum() 을 구현합니다. 그것은 여러분이 가리키고있는 원래의 객체가 어떻게 선언되었는지 전혀 알지 못합니다. 그 정보로 포인터를 태그 화 한 컴파일러를 작성하는 것은 가능할 것입니다. 그러나 많은 실제적인 이유 때문에 오늘날 실제로 사용되는 컴파일러는 없습니다 .¹

전체 프로그램 최적화로 다시 컴파일 할 수없는 공유 라이브러리에있을 수있는 sum() 내부에는 변경할 수없는 메모리에 대한 포인터 만 있습니다. 실제로, 일부 구현에서는 const 포인터를 통해 쓰려고하면 메모리 보호 오류로 프로그램이 중단 될 수 있습니다. 그리고 메모리 블록을 다른 유형으로 재 해석하는 기능은 C / C ++에서 중요합니다. 예를 들어, memset() 또는 memcpy() 는 임의의 바이트 배열로 재 해석합니다. 따라서 sum() 구현하면 포인터 인수의 출처를 알 수 없습니다. 그것까지는 const int[] 대한 포인터 일뿐입니다.

더 중요한 것은 함수의 계약에 따르면 포인터를 통해 객체를 수정하지 않는다는 것입니다 .² 단순히 const 한정자를 명시 적으로 버릴 수는 있지만 논리 오류가됩니다. 포인터를 const 선언하는 경우, 총에 안전을 부여하는 것과 같습니다. 컴파일러가 발에서 자신을 쏘지 못하게 하려고 합니다.

¹ 포인터에서 주소를 추출하기위한 추가 지침, 포인터를 저장하기위한 추가 메모리, 아키텍처에 대한 표준 호출 규칙과의 호환성, 포인터를 long 보유 할 수 있다고 가정하는 많은 기존 코드 위반 및 어떤 이익이든.

² mutable 데이터 멤버를 제외하면


실행시에 그것은 const 객체 일 수 있습니다. 즉, 역 참조에 대해 수행 된 모든 연산은 const와 호환 가능해야합니다. 예제에서 const가 아닌 객체를 가리키고 다른 것을 가리킬 수 없다는 사실을 무시하면 언어는 그렇게 작동하지 않습니다.


여기에는 다른 답변이 많이 있지만, 많은 사람들이 너무 많은 세부 정보를 제공하거나, 주제를 벗어나거나 OP에 거의없는 C ++ 전문 용어에 대한 지식을 갖고 있다고 생각하기 때문에이 글을 올릴 수있게되었습니다. 나는 그것이 그들의 직업의 비슷한 단계에서 OP와 다른 사람들에게 도움이되지 않는다고 생각한다. 그래서 나는 그것들 중 일부를 자르려고 노력할 것이다.

상황 자체는 실제로 매우 간단합니다. 선언문 :

const SomeClassOrType *p = ...

p가 가리키는 포인터는 포인터를 통해 수정할 수 없다고 말하면 p를 통해 해당 객체에 대한 액세스 권한을 얻은 코드가 예상치 못한 포인터를 수정하지 않도록하는 것이 유용합니다. 함수 선언은 매개 변수 선언에서 가장 많이 사용되어 함수와 메소드가 전달되는 객체 (*)를 수정할 수 있는지 여부를 알 수 있도록합니다.

실제로 지적되고있는 것의 상상력에 대해서는 전혀 말하지 않습니다. 포인터 자체는 단순한 영혼 일 뿐이며 그 정보를 가지고 다니지 않습니다. 포인터와 관련 하여 가리키는 객체는 읽을 수 있지만 기록 할 수 없다는 것을 알고 있습니다.

구체적인 예 (CiaPan에서 도난) :

void PrintString (const char *string);

char string [] = "abcde";
const char *p = string;
PrintString (p);

void PrintString (const char *ptr_to_string)
{
    ptr_to_string [0] = 0;   // oops!  but the compiler will catch this, even though the original string itself is writeable
}

매개 변수도 const로 선언 되었기 때문에 stringPrintString 직접 전달할 수 있습니다.

이것을 보는 또 다른 방법은 컴파일러가 컴파일 타임에 코드의 정확성 / 일관성을 검사하는 것을 돕기 위해 프로그래머가 제공하는 정보입니다. 컴파일러는 위와 같은 오류를 catch하고 더 나은 최적화를 수행 할 수 있습니다. 실제로 코드를 실행하면 역사가됩니다.

(*) 현대 관용구는 아마도 const 참조를 사용하는 것이지만, 나는 그것을 주요 논의에 던져서 물을 진흙 투성이가되고 싶지는 않다.


표현식의 유형은 표현식의 변수의 선언 된 유형을 기반으로하며 동적 런타임 데이터에 의존 할 수 없습니다. 예를 들어 다음과 같이 작성할 수 있습니다.

object a1;
const object a2;
const object *b;
if (rand() % 2 == 0) {
    b = &a1;
} else {
    b = &a2;
}
(*b);

*b 유형은 컴파일 타임에 결정되며, 프로그램을 실행할 때 rand() 반환하는 것에 의존 할 수 없습니다.

bconst object 를 가리 키도록 선언 되었기 때문에 *b 유형이 그 것이다.


const 키워드는 '개체를 수정할 수 없습니다.'가 아니라 '해당 개체를 수정할 수 없습니다'라는 의미입니다.

이는 객체의 값을 사용하지만 수정할 수는 없지만 객체를 일부 함수로 전달할 때 유용합니다.

// We expect PrintMyString to read the string
// and use its contents but not to modify it

void PrintMyString(const char *string);

void myfunction(int number)
{
    // build and print a string of stars with given length
    if(number>0 && number<=16]
    {
        char string[17];
        int i;
        for(i=0, i<number; i++)
            string[i] = '*';
        string[number] = '\0';

        PrintMyString(string);
    }
}

PrintMyString 함수는 문자 배열을 가져 PrintMyString 배열은 함수에 '읽기 전용'으로 전달됩니다. 배열은 소유 함수 내에서 확실히 수정할 수 있지만 PrintMyString 은 내용을 읽지 만 내용을 변경하지 않습니다.


const object* b = &a;

이것은 다음을 의미합니다. b는 const (읽기 전용) 객체에 대한 포인터입니다.

const 정도에 대해서는 아무 말도하지 않습니다. 단지 bb 를 수정할 권리가 없다는 것을 의미 a .

저수준 const 라고도합니다.

위와 반대로 최상위 레벨의 const 는 포인터 자체가 const 입니다.

object *const b = &a;   // b is a const pointer to an object

b = &some_other_object; // error - can't assign b to another object
                        // since b is a const pointer

*b = some_value;        // this is fine since object is non-const






c++