const(컴퓨터 프로그래밍)
const (computer programming) C, C++, D, 자바스크립트, 줄리아프로그래밍 언어에서 const는 형식 한정자:[a] 데이터가 읽기 전용임을 나타내는 데이터 유형에 적용되는 키워드다. 상수를 선언하는 데 사용될 수 있지만, const
C 언어 제품군에서 언어 유형은 유형의 일부라는 점에서 다른 언어의 유사한 구성 요소와 다르며, 따라서 포인터, 참조, 복합 데이터 유형 및 유형 확인과 결합할 때 복잡한 동작을 가진다.
소개
객체 선언에서 적용할 때,[b] 그것은 객체가 상수임을 나타낸다. 그 값은 변수와 달리 변경되지 않을 수 있다. 상수를 선언하기 위해 이러한 기본적인 용도는 다른 많은 언어와 유사하다.
그러나, 다른 언어들과는 달리, C 언어군에서는 const
유형의 일부일 뿐 개체의 일부가 아니다. 예를 들어, C에서, int const x = 1;
사물을 선언하다. x
의 int const
타이프 – the const
마치 에이다님에 있을 때 (intonst) x"를 구문 분석하듯, 타입의 일부분이다. X : constant INTEGER := 1_
상수(물체의 일종)를 선언하다 X
의 INTEGER
유형: constant
대상의 일부지만 유형의 일부는 아니다.
이것은 두 가지 미묘한 결과를 가지고 있다. 일단. const
예를 들어, 보다 복잡한 유형의 부분에 적용할 수 있다. int const * const x;
상수 정수에 대한 상수 포인터를 선언하는 동안 int const * x;
변수 포인터를 상수 정수로 선언하고 int * const x;
변수 정수에 대한 상수 포인터를 선언한다. 둘째로, 왜냐하면 const
유형의 일부인 경우, 형식 지정의 일부로서 일치해야 한다. 예를 들어, 다음 코드는 유효하지 않다.
공허하게 하다 f(인트로& x); // ... 인트로 경시하다 i; f(i);
에 대한 주장 때문에. f
변수 정수여야 하지만 i
상수 정수. 이 일치는 프로그램 정확성의 한 형태로서, 항상 정확하다고 알려져 있다. 이것은 계약별 프로그래밍 형식을 허용하는데, 여기서 함수는 자신의 주장을 수정하는지 여부와 반환가치가 수정 가능한지 여부를 유형 서명의 일부로 명시한다. 이러한 형식 점검은 주로 포인터와 참고 문헌(정수와 같은 기본 값 유형이 아니라 복합 데이터 유형 또는 컨테이너와 같은 템플리트 유형)에 관심이 있다. 라는 사실에 감춰져 있다. const
유형 강제(불확실한 유형 변환)와 C가 호별(C++와 D는 호별 또는 호별)이기 때문에 종종 생략할 수 있다.
결과들
항상성의 개념은 그것이 컴퓨터 메모리에 저장되는 변수가 읽을 수 없다는 것을 의미하지 않는다. 오히려 const
-ness는 프로그래머가 해야 할 일을 나타내는 컴파일 시간 구조로, 반드시 할 수 있는 일이 아니다. 그러나 미리 정의된 데이터의 경우(예: char const *
문자열 리터럴), C const
종종 비판할 수 없다.
상수와 구별
프로그램이 실행되는 동안 상수가 값을 변경하지 않는 동안 개체가 선언됨 const
프로그램이 실행되는 동안 정말로 그것의 가치가 바뀔 수 있다. 일반적인 예로는 디지털 입력의 현재 상태와 같은 임베디드 시스템 내의 읽기 전용 레지스터가 있다. 디지털 입력에 대한 데이터 레지스터는 종종 다음과 같이 선언된다. const
그리고 volatile
이 등록부의 내용은 프로그램이 아무 것도 하지 않아도 바뀔 수 있다.volatile
( ) 그러나 당신은 그들에게도 편지를 쓸 수 없다.const
).
기타 용도
또한 a (비정적) 멤버 기능을 다음과 같이 선언할 수 있다. const
. 이 경우, 그러한 함수 내부의 포인터는 유형이다. object_type const *
단순한 활자라기 보다는 object_type *
즉,[1] 이러한 함수 내부에서 이 객체에 대해 일정하지 않은 함수를 호출할 수 없으며, 멤버 변수를 수정할 수도 없다. C++에서 멤버 변수는 다음과 같이 선언할 수 있다. mutable
, 이 제한이 그것에 적용되지 않음을 나타낸다. 예를 들어 캐싱, 참조 카운트 및 데이터 동기화와 같은 경우에 유용할 수 있다. 이 경우 객체의 논리적 의미(상태)는 변하지 않지만, 비트(bitwise) 표현이 바뀔 수 있기 때문에 물체는 물리적으로 일정하지 않다.
구문
C, C++, D에서는 사용자가 정의한 데이터 유형을 포함한 모든 데이터 유형을 선언할 수 있다. const
그리고 항상 정확성은 수정될 필요가 없는 한 모든 변수나 물체를 이와 같이 선언해야 한다는 것을 지시한다. 이러한 사전 예방적 사용 const
가치관을 "이해, 추적, 추론"[2]하게 하고, 따라서 코드의 가독성과 이해도를 높이고, 가치의 의도된 용도에 대한 정보를 전달하기 때문에 팀으로 작업하고 코드를 유지관리하는 것이 더 간단해진다. 이는 코드 추론 시 개발자뿐만 아니라 컴파일러에게도 도움이 될 수 있다. 또한 최적화 컴파일러가 보다 효율적인 코드를 생성할 수 있도록 할 수 있다.[3]
단순 데이터 유형
단순한 비점퍼 데이터 유형의 경우 const
한정자는 간단하다. 그것은 역사적 이유로 일부 유형의 어느 한쪽으로 갈 수 있다(예를 들어, const char foo = 'a';
와 같다 char const foo = 'a';
. 일부 구현에 대해 다음을 사용 const
두 번(예를 들어, const char const
또는 char const const
)는 경고를 생성하지만 오류는 생성하지 않는다.
포인터 및 참조
포인터 및 참조 유형의 경우 const
더 복잡하다 - 포인터 자체 또는 포인터가 가리키는 값 또는 둘 다 const
더 나아가 구문은 혼란스러울 수 있다. 포인터는 a로 선언할 수 있다. const
쓰기 가능한 값에 대한 포인터 또는 쓰기 가능한 에 대한 포인터 const
가치 또는 const
을 가리키다. const
가치 A const
포인터가 처음에 할당된 개체와 다른 개체를 가리키도록 다시 할당할 수는 없지만 포인터가 가리키는 값(양자리라고 함)을 수정하는 데 사용할 수 있다. C++의 참조 변수는 다음에 대한 대체 구문입니다. const
포인터 에 대한 포인터 const
반면에 객체는 다른 메모리 위치(동일한 유형의 객체 또는 변환형 객체여야 함)를 가리키도록 재할당될 수 있지만, 그것이 가리키는 메모리를 수정하는 데는 사용할 수 없다. a const
에 대한 포인터. const
또한 개체는 선언될 수 있고, 다른 개체를 가리키도록 재지정될 수도 없다. 다음 코드는 이러한 미묘함을 예시한다.
공허하게 하다 푸( 인트로 * 삐걱삐걱거리다, 인트로 경시하다 * ptrToConst, 인트로 * 경시하다 constPtr, 인트로 경시하다 * 경시하다 ConstPtrToConst ) { *삐걱삐걱거리다 = 0; // 확인: "시" 데이터 수정 삐걱삐걱거리다 = NULL; // OK: 포인터를 수정한다. *ptrToConst = 0; // 오류! "권한" 데이터를 수정할 수 없음 ptrToConst = NULL; // OK: 포인터를 수정한다. *constPtr = 0; // 확인: "시" 데이터 수정 constPtr = NULL; // 오류! 포인터를 수정할 수 없음 *ConstPtrToConst = 0; // 오류! "권한" 데이터를 수정할 수 없음 ConstPtrToConst = NULL; // 오류! 포인터를 수정할 수 없음 }
C 컨벤션
선언에 대한 통상적인 C 규약에 따라, 선언은 용도에 따르고, 선언은 다음과 같다. *
포인터가 포인터 위에 쓰여져 있고, 비참조를 나타낸다. 예를 들어 선언에서 int *ptr
, 참조 해제 양식 *ptr
이다 int
, 참조 양식 동안 ptr
에 대한 포인터다. int
. 따라서. const
이름을 오른쪽으로 바꾸다 C++ 규칙은 대신 를 연결하는 것이다. *
와 같이 타입을 가지고. int* ptr,
그리고 그 책을 읽다 const
활자를 왼쪽으로 수정하는 것. int const * ptrToConst
따라서 "라고 읽힐 수 있다.*ptrToConst
a이다 int const
"(값이 일정하다), 또는 "ptrToConst
a이다 int const *
" ( 포인터는 정수를 가리키는 포인터다.) 따라서 다음과 같다.
인트로 *삐걱삐걱거리다; // *ptr은 int 값임 인트로 경시하다 *ptrToConst; // *ptrToConst는 상수(int: 정수 값) 인트로 * 경시하다 constPtr; // ConstPtr은 상수(*: 정수 포인터) 인트로 경시하다 * 경시하다 ConstPtrToConst; // ConstPtrToConst는 상수(점자) // 그대로 *constPtrToConst(값)
C++ 컨벤션
값이 아닌 활자를 분석하는 C++ 관례를 따라 좌우에서 선언문을 읽는 것이 주먹구구식이다. 따라서 별의 왼쪽에 있는 모든 것은 포인티 타입으로 식별될 수 있고, 별의 오른쪽에 있는 모든 것은 포인터 속성이다. 예를 들어, 위의 예에서, int const *
쓰기 불가능한 정수를 가리키는 쓰기 가능한 포인터로 읽을 수 있으며, int * const
쓰기 가능한 정수를 나타내는 쓰기 불가능한 포인터로 읽을 수 있다.
복잡한 선언 및 정의를 이해하는 데 도움이 되는 보다 일반적인 규칙은 다음과 같이 작동한다.
- 이해하려는 선언의 식별자를 찾으십시오.
- 가능한 한 오른쪽으로 읽는다(즉, 선언이 끝날 때까지 또는 다음 닫는 괄호 중 먼저 오는 것이 좋다).
- 시작 위치로 돌아가서 왼쪽으로 거꾸로 읽으십시오(예: 선언이 시작될 때까지 또는 이전 단계에서 찾은 닫힘 괄호와 일치하는 열린 괄호로 이동).
- 선언의 시작에 도달하면 당신은 끝장이다. 그렇지 않으면 마지막으로 일치하는 닫힌 괄호 너머의 2단계에서 계속하십시오.
예를 들면 다음과 같다.
표현의 일부 | 곱절로 하다 (**경시하다 (*재미있다(인트로))(곱절로 하다))[10] | 의미 (아래로 읽음) |
---|---|---|
식별자 | 재미있다 | fun 그것은 ...이다. |
오른쪽으로 읽어라 | (인트로)) | ...을 기대하다. |
일치하는 항목 찾기( | (* | ...에게 포인터를 돌려주다. |
오른쪽 계속 | (곱절로 하다)) | ...의 더블을 기대하는 기능. |
일치하는 항목 찾기( | (**경시하다 | 에 대한 상수 포인터 반환 ...의 포인터. |
오른쪽 계속 | [10] | 10블록의 ... |
왼쪽으로 읽어라 | 곱절로 하다 | 배가 되다 |
왼쪽을 읽을 때는 오른쪽에서 왼쪽으로 원소를 읽는 것이 중요하다. 그래서 안 int const *
int에 대한 포인터가 되고 int에 대한 포인터가 되지 않는다.
경우에 따라 C/C++는 다음을 허용한다. const
유형 왼쪽에 배치할 키워드 여기 몇 가지 예가 있다.
경시하다 인트로 *ptrToConst; //Identificate to: in const *ptrToConst, 경시하다 인트로 *경시하다 ConstPtrToConst; //Identicate to: inst const *const constPtrToConst
C/C++는 그러한 정의(왼쪽부터 오른쪽까지 정의를 읽을 때 영어와 밀접하게 일치하는 정의)를 허용하지만, 컴파일러는 여전히 위에서 언급한 절차에 따라 정의를 읽는다. 그러나 퍼팅 const
상수여야 할 것이 빨리 당신이 쓰려고 하는 것과 컴파일러가 당신이 쓰기로 결정한 것 사이의 불일치를 소개하기 전에. 포인터의 포인터를 고려하십시오.
인트로 **삐걱삐걱거리다; // int에 대한 포인터 인트로 경시하다 **삐걱삐걱거리다 // 상수 int 값에 대한 포인터 // (int에 대한 상수 포인터를 가리키는 포인터가 아님) 인트로 *경시하다 *삐걱삐걱거리다 // int 값에 대한 항상 포인터 // (int에 대한 포인터에 대한 일정한 포인터가 아님) 인트로 **경시하다 삐걱삐걱거리다 // int에 대한 포인터에 대한 상수 포인터 // (ptr, 식별자, constitution이라는 것은 말이 안 된다. 인트로 경시하다 **경시하다 삐걱삐걱거리다 // 상수 int 값에 대한 포인터에 대한 상수 포인터
포인터 정의에 대한 마지막 참고 사항으로, 항상 포인터 기호(*)를 가능한 한 오른쪽에 기록하십시오. 포인터 기호를 타입에 부착하는 것은 포인터 타입을 강하게 암시하기 때문에 까다롭다. 여기 몇 가지 예가 있다.
인트로* a; /* 쓰기: */ 인트로 *a; // a는 int에 대한 포인터 인트로* a, b; // 혼란스러운 /* 쓰기: */ 인트로 *a, b; // a는 int에 대한 포인터로, // 그러나 b는 단지 int에 불과하다. 인트로* a, *b; // WANGE: a와 b는 모두 인트의 포인터다. /* 쓰기: */ 인트로 *a, *b;
Bjarne Strustrup의 FAQ는 이 문제를 피하기 위해 C++ 규약을 사용할 경우 한 줄에 한 변수만 선언할 것을 권고한다.[4]
참조 및 rvalue 참조 정의에도 동일한 고려 사항이 적용된다.
인트로 시합을 하다 = 22; 인트로 경시하다 &refToConst = 시합을 하다; // OK 인트로 경시하다& ref2 = 시합을 하다, ref3 = 시합을 하다; // 혼동: // ref2는 참조사항이지만 ref3는 다음과 같지 않다. // ref3는 로 초기화되는 상수 int이다. // var의 값 인트로 &경시하다 콘스트레프 = 시합을 하다; // 오류: 참조는 어차피 변경될 수 없기 때문에. // C++: 인트로&& rref = 인트로(5), 가치를 매기다 = 10; // 혼동: // rref는 rvalue reference이지만 값은 // 단순한 int. /* 쓰기: */ 인트로 &&rref = 인트로(5), 가치를 매기다 = 10;
다차원 배열과 포인터 참조(또는 포인터)를 사용할 때 보다 복잡한 선언이 발생한다. 간혹 그러한 선언이 혼동되고 오류가 발생하기 쉬우며 따라서 이를 피하거나 상위 수준의 구조로 대체해야 한다는 주장이[who?] 제기되지만, 이 조의 상단에서 설명한 절차는 모호성이나 혼동을 초래하지 않고 항상 사용할 수 있다.
모수 및 변수
const
함수 매개변수와 변수 둘 다에서 선언할 수 있다(정적 또는 자동, 전역 또는 로컬 포함). 해석은 용도에 따라 다르다. a const
정적 변수(전지구 변수 또는 정적 로컬 변수)는 상수로, 다음과 같은 수학적 상수와 같은 데이터에 사용할 수 있다. double const PI = 3.14159
– 현실적으로 더 길거나 전체 컴파일 시간 매개변수 a const
자동 변수(비정적 로컬 변수)는 단일 할당이 발생하고 있음을 의미하지만, 예를 들어, 매번 다른 값을 사용할 수 있다. int const x_squared = x * x
…. const
Pass-by-Reference의 매개변수는 참조된 값이 수정되지 않고 계약의 일부인 것을 의미한다. const
Pass-by-by-reference(또는 포인터 자체, pass-by-by-reference)의 파라미터는 인터페이스에 아무것도 추가하지 않지만, 내부적으로 함수가 파라미터의 로컬 복사본을 수정하지 않는다는 것을 나타낸다(단일 할당). 이러한 이유로, 어떤 사람들은 const
계약변경이 이루어지는 기준별 매개변수에만 적용되며, 기준별 매개변수에는 적용되지 않으며, 가치별 매개변수는 구현이 노출된다.
C++
방법들
사용자 정의 유형(구조물 및 클래스)에 대한 계약 접근법에 의한 설계의 이점을 활용하기 위해, 프로그래머는 다음과 같이 인스턴스(instance) 방법에 태그를 붙일 수 있다. const
개체의 데이터 구성원을 수정하지 않는 경우 적용하기 const
따라서 인스턴스(instance) 메서드에 대한 한정자는 항상 정확성을 위해 필수적인 기능이며, Java 및 C#와 같은 많은 다른 객체 지향 언어 또는 Microsoft의 C++/CLI 또는 C++용 Managed Extensions에서는 사용할 수 없다. 동안 const
방법은 에 의해 호출될 수 있다. const
비-비const
마찬가지로, 비-물체const
비-비-에 의해서만 호출할 수 있는 방법const
물건들 그 const
인스턴스(instance) 방법의 수식어가 "로 가리키는 객체에 적용된다.this
" pointer, 이것은 모든 인스턴스 방법에 전달된 암묵적 인수다. 따라서 가지고 있는 const
방법은 암시적인 "에 대해 항상 정확성을 적용하는 방법이다.this
" 다른 주장들과 마찬가지로 포인터 논쟁.
이 예는 다음을 예시한다.
계급 C { 인트로 i; 공중의: 인트로 얻다() 경시하다 // "const" 태그를 기록해 두십시오. { 돌아오다 i; } 공허하게 하다 세트(인트로 j) // "const"의 부족에 유의 { i = j; } }; 공허하게 하다 푸(C& 비콘스터C, C 경시하다& 콘스트C) { 인트로 y = 비콘스터C.얻다(); // OK 인트로 x = 콘스트C.얻다(); // OK: Get()은 항상이다. 비콘스터C.세트(10); // 확인: 비콘스터C는 수정할 수 있음 콘스트C.세트(10); // 오류! Set()는 비정수 방법이고 constC는 시공 자격 객체다. }
위의 코드에서 암묵적인 "this
을 가리키다. Set()
타입 "이 있다.C *const
"; 반면에 "this
을 가리키다. Get()
형식 "이 있다.C const *const
", 메서드가 "를 통해 개체를 수정할 수 없음을 나타냄this
" 포인터.
종종 프로그래머는 두 가지 모두를 제공할 것이다. const
그리고 비-비-.const
두 유형의 발신자를 수용하기 위해 클래스에 이름이 같지만 상당히 다른 용도를 가진 방법. 고려 사항:
계급 마이어레이 { 인트로 자료[100]; 공중의: 인트로 & 얻다(인트로 i) { 돌아오다 자료[i]; } 인트로 경시하다 & 얻다(인트로 i) 경시하다 { 돌아오다 자료[i]; } }; 공허하게 하다 푸( 마이어레이 & 배열하다, 마이어레이 경시하다 & ConstArray ) { // 배열 요소에 대한 참조 가져오기 // 참조된 값을 수정하십시오. 배열하다.얻다( 5 ) = 42; // OK! (통화: int & MyArray:::가져오기(입력) ConstArray.얻다( 5 ) = 42; // 오류! (통화: int const & MyArray:::Get (int) constance) }
그 const
-호출 객체의 ness가 의 버전을 결정한다. MyArray::Get()
호출자가 개체의 개인 데이터만 관찰하거나 조작할 수 있는 참조가 제공되는지 여부. 두 방법은 기술적으로 서명이 다르다. 왜냐하면 그들의 "this
" 포인터는 종류가 다르기 때문에 컴파일러가 올바른 포인터를 선택할 수 있다. (반복) const
에 대한 언급. int
, 단지 반환하는 대신에 int
값 별, 두 번째 방법에서는 과잉 살상이 될 수 있지만, 표준 템플릿 라이브러리에서와 같이 임의 유형에서도 동일한 기술을 사용할 수 있다.)
항상 정확성에 대한 허점
C와 C++에는 순전히 모든 것을 바로잡을 수 있는 몇 가지 허점이 있다. 그것들은 주로 기존 코드와의 호환성을 위해 존재한다.
C++에만 적용되는 첫 번째 방법은 const_cast
프로그래머가 그 옷을 벗길 수 있게 해준다. const
한정자, 임의의 객체 수정 가능. 한정자 박멸의 필요성은 기존 코드와 수정될 수는 없지만 항상 정확하지는 않은 라이브러리를 사용할 때 발생한다. 예를 들어 다음 코드를 고려하십시오.
// 변경할 수 없는 기능의 프로토타입 // 우리는 합격자를 수정하지 않는다는 것을 안다. 공허하게 하다 라이브러리펑크(인트로* 삐걱삐걱거리다, 인트로 사이즈를 맞추다); 공허하게 하다 캘리브라리펑크(인트로 경시하다 * 삐걱삐걱거리다, 인트로 사이즈를 맞추다) { 라이브러리펑크(삐걱삐걱거리다, 사이즈를 맞추다); // 오류! Drops const 한정자 인트로* 비콘스탄트Ptr = const_cast<인트로*>(삐걱삐걱거리다); // 스트립 한정자 라이브러리펑크(비콘스탄트Ptr, 사이즈를 맞추다); // OK }
그러나, 그 자체가 선언된 객체를 수정하려는 모든 시도 const
항상 캐스팅을 통해 ISO C++ 표준에 따라 정의되지 않은 동작이 발생한다. 위의 예에서 다음과 같은 경우 ptr
로 선언된 전역, 로컬 또는 멤버 변수를 참조한다. const
또는 힙에 할당된 개체 new int const
, 코드는 오직 다음의 경우에 정확하다. LibraryFunc
실제로 다음을 가리키는 값을 수정하지 않음 ptr
.
C언어는 일정한 상황이 존재하기 때문에 허점이 필요하다. 정적 저장 지속시간이 있는 변수는 초기 값으로 정의할 수 있다. 그러나 이니셜라이저는 문자열 상수 및 기타 리터럴과 같은 상수만 사용할 수 있으며, 이니셜라이저 요소가 선언되어 있는지 여부에 관계없이 변수 이름과 같은 비정수 요소를 사용할 수 없다. const
또는 정적 지속 시간 변수가 선언되는지 여부 const
그렇지 않으면. 초기화하는 비이동적 방법이 있다. const
정적 스토리지 기간이 있는 변수. 나중의 과제의 왼쪽에 타이프캐스트를 신중하게 구성함으로써 a. const
변수를 효과적으로 제거하여 const
다른 요소와 같이 비파생적인 요소들로 그것을 속성과 '비파생화'한다. const
변수 등 에 쓰기 const
가변적인 이 방법은 의도한 대로 작동할 수 있지만, 정의되지 않은 행동을 유발하며, 항상 정확성과 심각하게 모순된다.
size_t 경시하다 bufferSize = 8*1024; size_t 경시하다 userTextBufferSize; //초기 값은 const bufferSize에 따라 달라지므로 여기서 초기화할 수 없음 ... 인트로 setupUserTextBox(textBox_t *defaultTextBoxType, 직장_t *defaultTextBoxLocation) { *(size_t*)&userTextBufferSize = bufferSize - 의 크기(구조상의 textBoxControls); // 경고: 효과가 있을 수 있지만 C에 의해 보장되지 않음 ... }
또[5] 다른 허점은 C와 C++ 모두에 적용된다. 구체적으로, 언어들은 회원 포인터와 참고문헌이 회원 포인터와 관련하여 "허용"이라고 지시한다. const
-소유자의 ness — 즉, 포함된 물체가 const
모두 가지고 있다 const
멤버 지명자(및 심판)를 제외한 멤버들은 여전히 변이 가능하다. 예를 들어, 다음 C++ 코드를 고려하십시오.
구조상의 S { 인트로 발랄하게 하다; 인트로 *삐걱삐걱거리다; }; 공허하게 하다 푸(S 경시하다 & s) { 인트로 i = 42; s.발랄하게 하다 = i; // 오류: s는 항상이므로 val은 항상이다. s.삐걱삐걱거리다 = &i; // 오류: s는 항상이므로 ptr은 int에 대한 항상 포인터가 된다. *s.삐걱삐걱거리다 = i; // OK: ptr이 가리키는 데이터는 항상 변이 가능하며, // 때로는 바람직하지 않지만 }
비록 그 물체는 s
에 전달된. Foo()
일정하며, 모든 구성원을 일정하게 만들고, 그 구성원을 통해 접근할 수 있다. s.ptr
비록 이것이 의 관점에서 바람직하지 않을 수 있지만, 여전히 수정할 수 있다. const
-정확성 이유 s
지명자만을 소유할 수도 있어 이 때문에 마이어스는 회원 포인터와 참고문헌의 디폴트(디폴트)가 '딥(deep)'이어야 한다고 주장한다. const
-ness, 에 의해 오버라이드될 수 있음 mutable
컨테이너 소유자가 아닌 한정자. 그러나 이 전략은 기존 코드와의 호환성 문제를 일으킬 것이다. 따라서 역사적 이유로[citation needed] 이러한 허점은 C와 C++에 열려 있다.
후자의 허점은 a 뒤에 포인터를 숨기기 위해 클래스를 사용함으로써 닫힐 수 있다. const
-정확한 인터페이스, 그러나 그러한 클래스는 a의 일반적인 카피 의미론을 지원하지 않는다. const
객체(포함된 클래스를 일반적인 의미론적으로 복사할 수 없음) 또는 박리를 허용하여 다른 허점을 허용함 const
-의도하지 않거나 의도적인 복사를 통해 알 수 없음.
마지막으로, C 표준 라이브러리의 여러 기능은 a를 수용하기 때문에 const-correctness를 위반한다. const
문자열에 포인터를 대고 비문자를 반환하십시오.const
같은 문자열의 일부에 대한 포인터 strtol
그리고 strchr
이러한 기능들 중 하나이다. C++ 표준 라이브러리의 일부 구현, 예를 들어 Microsoft가 일부 기능의 과부하 버전을 제공함으로써 이러한 허점을 닫으려 하는 경우[6]: "const
버전과 비 버전const
" 버전.
문제
![]() | 이 구간은 확장이 필요하다. 추가하면 도움이 된다. (2014년 11월) |
항상성을 표현하기 위해 형식 시스템을 사용하는 것은 여러 가지 복잡성과 문제로 이어지며, 그에 따라 C, C++, D의 좁은 C 계열 밖에서는 비판받고 채택되지 않았다. C와 C++의 영향을 많이 받는 자바와 C#, 둘 다 명시적으로 거부되었다. const
-style type 한정자, 대신 식별자에 적용되는 키워드별로 항상성을 표현한다(final
자바에서는 const
그리고 readonly
C#)로 C와 C++ 안에서도 의 사용법 const
일부 프로젝트 및 조직에서 일관성 있게 사용하고 다른 조직에서는 이를 회피하는 등 상당히 다양하다.
strchr
문제
그 const
형식 한정자는 어떤 함수의 논리가 그 입력이 일정한지 여부에 영향을 미치지 않지만, 입력과 동일한 형식이어야 하는 값을 반환할 때 어려움을 야기한다. 즉, 이러한 기능의 경우, 입력이 일정하면(정규격) 반환값도 같아야 하지만, 입력이 가변적인 경우에는(정규격은 아님) 반환값도 같아야 한다. const
-적격), 반환 값도 같아야 한다. 이러한 기능의 형식 서명이 다르기 때문에, 동일한 논리의 두 가지 기능(또는 복수의 입력의 경우, 잠재적으로 그 이상)이 필요하다. 즉, 일반적인 프로그래밍의 한 형태.
이 문제는 특히 C 표준 라이브러리의 간단한 기능에도 발생한다. strchr
; 이 관찰은 1980년대 중반에 Ritchie가 Tom Flume에게 돌렸다.[7] 그 strchr
함수는 문자열에서 문자를 찾으며, 형식적으로는 문자가 처음 나타나는 곳에 포인터를 반환한다. c
현악기에 빠져 s
, 그리고 Classic C (K&R C)에서 그것의 프로토타입은 다음과 같다.
마를 뜨다 *발을 동동 구르다(마를 뜨다 *s, 인트로 c);
그 strchr
함수는 입력 문자열을 수정하지 않지만, 반환 값은 발신자가 문자열을 수정하기 위해 다음과 같이 자주 사용된다.
만일 (p = 발을 동동 구르다(q, '/')) *p = ' ';
따라서 입력 문자열은 한 편으로 const
(함수에 의해 수정되지 않기 때문에) 및 입력 문자열이 const
첫 번째 문자가 일치하는 경우 입력 포인터를 정확하게 반환할 수 있기 때문에 반환 값도 같아야 하지만 다른 한편으로는 반환 값이 같아야 한다. const
원래의 끈이 아니라면 const
호출자가 포인터를 사용하여 원래 문자열을 수정하려고 할 수 있으므로 .
C++에서 이 작업은 기능 과부하를 통해 수행되며, 일반적으로 템플릿을 통해 구현되며, 결과적으로 두 가지 기능이 발생하여 반환 값이 동일하다. const
-입력 형식:[c]
마를 뜨다* 발을 동동 구르다(마를 뜨다* s, 인트로 c); 마를 뜨다 경시하다* 발을 동동 구르다(마를 뜨다 경시하다* s, 인트로 c);
템플릿으로 다음 사항을 정의할 수 있다.
템플릿 <T> T* 발을 동동 구르다(T* s, 인트로 c) { ... }
D에서 이 작업은 다음을 통해 처리된다. inout
constitute, 불변 또는 무자격(무자격)의 와일드카드 역할을 하는 키워드, 다음과 같은 결과를 낳는다.[8][d]
밖으로(마를 뜨다)* 발을 동동 구르다(밖으로(마를 뜨다)* s, 인트로 c);
그러나 C에서는 C가 함수 과부하를 가지지 않기 때문에 이 두 가지 중 어느 것도 가능하지 않으며, 대신 입력은 일정하지만 출력은 쓰기 가능한 단일 함수를 갖는 것으로 처리된다.
마를 뜨다 *발을 동동 구르다(마를 뜨다 경시하다 *s, 인트로 c);
이것은 관용적인 C 코드를 허용하지만, 만약 입력이 실제로 형식 안전을 위반하는, 시공 자격증을 박탈한다. 이 해결책은 Ritchie에 의해 제안되었고 이후 채택되었다. 이 차이는 C와 C++의 호환성 실패의 하나이다.
D
D 프로그래밍 언어 버전 2에는 항상성과 관련된 두 개의 키워드가 있다.[9] 그 immutable
키워드는 어떤 참조로도 수정할 수 없는 데이터를 가리킨다. 그 const
키워드는 변경 불가능한 데이터 보기를 가리킨다. C++와 달리 const
d const
그리고 immutable
"깊다" 또는 "전환적이다" 그리고 어떤 것이든 a를 통해 도달할 수 있다. const
또는 immutable
목적어는 const
또는 immutable
각각
D에서 항상 대 불변의 예
인트로[] foo = 새로운 인트로[5]; // foo는 변이할 수 있다. 경시하다 인트로[] 술집을 내다 = foo; // bar는 변이 가능한 데이터의 항상 보기입니다. 불변의 인트로[] 야유하다 = foo; // 오류: 불변 데이터의 모든 보기는 불변해야 한다. 불변의 인트로[] 숫자 = 새로운 불변의(인트로)[5]; // 숫자에 대한 변이 가능한 참조는 생성할 수 없다. 경시하다 인트로[] constNums = 숫자; // 작용한다. 불변은 은연중에 항상으로 전환된다. 인트로[] 변이 가능한Nums = 숫자; // 오류: 불변 데이터의 변경 불가능한 보기를 만들 수 없음.
D에서 transitive 또는 deep constance의 예
계급 푸 { 푸 다음에; 인트로 숫자; } 불변의 푸 foo = 새로운 불변의(푸); foo.다음에.숫자 = 5; // 컴파일하지 않는다. foo.next는 불변형(Foo)이다. // foo.next.num은 불변형(int)이다.
역사
const
1981년 C++의 전신인 C 클래스와 함께 Bjarne Strustrup에 의해 소개되었고, 원래 이름이 불렸다. readonly
.[10][11] 동기에 대해 스트루스트럽은 다음과 같이 쓰고 있다.[11]
- "범위와 유형 규칙(즉, 매크로를 사용하지 않고)을 준수하는 상징 상수를 정의하는 방법과 기억 속에 있는 물체를 불변으로 간주하는 방법 등 두 가지 기능을 수행했다."
매크로에 대한 범위와 타이핑된 대안으로서 첫 번째 용도는 매크로를 통해 기능적인 매크로에 대해 유사하게 충족되었다. inline
키워드 일정한 포인터 및 * const
데니스 리치가 제안하여 채택한 표기법.[11]
const
그런 다음 표준화의 일부로 C에서 채택되었으며, 다른 형식 한정자와 함께 C89(및 후속 버전)에 표시된다. volatile
.[12] 추가 한정자, noalias
는 1987년 12월 X3J11 위원회 회의에서 제안되었으나 거절당했고, 그 목표는 결국 X3J11에 의해 달성되었다. restrict
C99의 키워드. 리치는 이러한 추가 사항들이 "그들의 무게를 실어주지 않았다"고 주장하면서 별로 지지하지 않았지만, 결국 기준에서 제외되어야 한다고 주장하지는 않았다.[13]
D 후속 상속 const
C++에서, 형식 한정자가 아닌 형식 생성자로 알려져 있고 2개의 형식 생성자를 추가했다. immutable
그리고 inout
, 관련 사용 사례 처리.[e]
다른 언어
다른 언어는 종종 피상적으로 유사한 구조를 가지며 사용하기도 하지만 항상성 부분을 가지는데 있어서 C/C++를 따르지 않는다. const
키워드 일반적으로 이것은 상수(정수 객체)에만 사용된다.
C#은 a를 가지고 있다. const
키워드, 그러나 근본적으로 다르고 단순한 의미론적 의미론: 그것은 컴파일 시간 상수를 의미하며, 형식의 일부가 아니다.
Nim은 ~을 가지고 있다. const
C#의 그것과 유사한 키워드: 또한 타입의 일부를 형성하기 보다는 컴파일 시간 상수를 선언한다. 그러나 님에서는 컴파일 시간에 평가할 수 있는 어떤 표현에서도 상수를 선언할 수 있다.[14] C#에서는 C# 내장형만 다음과 같이 선언할 수 있다. const
; 클래스, 구조체 및 어레이를 포함한 사용자 정의 유형은 다음과 같을 수 없음 const
.[15]
Java에 다음이 없음 const
– 대신 final
로컬 "일반" 선언에 적용할 수 있으며 유형이 아닌 식별자에 적용할 수 있다. 명칭의 유래인 오브젝트 멤버를 위한 오브젝트 지향 용도가 다르다.
Java 언어 사양은 다음과 같다. const
예약된 키워드 - 즉, 가변 식별자로 사용할 수 없지만 의미론은 할당하지 않는 키워드: 예약된 단어(식별자에서는 사용할 수 없음)이지만 키워드(특별한 의미가 없음)는 아니다. 키워드 예약은 자바 언어의 확장에 C++-style이 포함되도록 하기 위해서 발생한 것으로 생각된다. const
에 대한 방법과 포인터 const
유형.[citation needed] 구현을 위한 개선 요청 티켓 const
정확성은 자바 커뮤니티 프로세스에 존재하지만, 역호환 방식으로 구현하는 것이 불가능하다는 이유로 2005년에 폐쇄되었다.[16]
현대의 Ada 83은 독립적으로 일정한 대상과 a의 개념을 가지고 있었다. constant
키워드([17][f]입력 파라미터 및 루프 파라미터가 암시적으로 일정함) 여기 더 constant
개체의 속성이지 유형의 속성이 아니다.
JavaScript에는 const
재할당하거나 다시 닫을 수 없는 블록 범위 변수를 정의하는 선언 다시 정의할 수 없는 변수에 대한 읽기 전용 참조를 정의하지만, 변수가 객체를 참조하고 그 속성이 변경되는 경우와 같이 변수 자체의 값이 잠재적으로 변경될 수 있는 경우도 있다.[18]
참고 항목
메모들
- ^ D에서 유형 생성자는 객체 지향 프로그래밍에서 생성자와 유사하게 형식 한정자 대신 사용된다.
- ^ 정식으로 ~할 때
const
선언문에서 가장 바깥으로 파생된 유형의 일부분이다. 포인터는 토론을 복잡하게 한다. - ^ 포인터 선언 구문 규칙은 C와 C++: C에서 서로 다르다는 점에 유의하십시오.
char *s
C++에 있는 동안 표준임char* s
표준이다. - ^ 관용 D 코드는 포인터 대신 여기에 배열을 사용한다.[8]
- ^ D는 또한 다음과 같은 것을 소개했다.
shared
생성자를 입력하지만 이는 다음 사용 사례와 관련이 있다.volatile
, 아니다.const
. - ^ 에이다 표준은 이것을 "예약된 단어"라고 부른다. 그 기사를 참고하여 사용하라.
참조
- ^ "The
this
pointer". Draft C++ Standard. Retrieved 2020-03-30.The type of
this
in a member function whose type has a cv-qualifier-seq cv and whose class isX
is “pointer to cvX
”. - ^ 허브 서터와 안드레이 알렉산드레스쿠(2005년). C++ 코딩 표준 페이지 30. 보스턴: 애디슨 웨슬리 ISBN 0-321-11358-6
- ^ "Why is the kfree() argument const?". lkml.org. 2013-01-12.
- ^ "Stroustrup: C++ Style and Technique FAQ".
- ^ 스콧 마이어스(2005년). 유효 C++, 제3판 21-23페이지. 보스턴: 애디슨 웨슬리 ISBN 978-0-321-33487-9
- ^ "strchr, wcschr, _mbschr (CRT)". Msdn.microsoft.com. Retrieved 2017-11-23.
- ^ "Dennis Ritchie: Why I do not like X3J11 type qualifiers".
- ^ a b D 프로그래밍 언어, Andrei Alexandrescu, 8.8: 매개 변수에서 결과로 한정자 전파
- ^ "const(FAQ) – D Programming Language". Digitalmars.com. Retrieved 2013-08-18.
- ^ Bjarne Stroustrup, "C Language Type Concept의 연장", Bell Labs 내부 기술 비망록, 1981년 1월 5일.
- ^ a b c 형제 경쟁: C와 C++, Bjarne Strustrup, 2002, 페이지 5
- ^ 데니스 M. 리치, "The Development of the C Language, 2012년 7월 15일, at archive.today.", 2003: "X3J11은 또한 형식 한정자의 항상성과 변동성, 그리고 약간 다른 형식 홍보 규칙과 같은 더 작은 추가와 조정들을 많이 도입했다.
- ^ 그는 "12월 이전 예선전('const'와 '휘발성')도 그들의 무게를 실어준다는 확신이 없다는 말로 시작하겠다"고 말했다. 특히 '휘발성'은 난해한 어플리케이션을 위한 프릴이며, 다른 수단으로 훨씬 잘 표현된다. 그것의 가장 큰 장점은 거의 모든 사람들이 그것에 대해 잊을 수 있다는 것이다. 'Const'는 더 유용하고 동시에 더 모호하다. 도서관 인터페이스에 존재하기 때문에 그것에 대해 배우는 것을 피할 수 없다. 그럼에도 불구하고 너무 늦었다고 해서 예선탈락을 주장하지는 않는다."
- ^ Nim Manual: 콘스탄트 섹션
- ^ const (C# 참조)
- ^ "Bug ID: JDK-4211070 Java should support const parameters (like C++) for code maintainence [sic]". Bugs.sun.com. Retrieved 2014-11-04.
- ^ 1815A[dead link], 3.2.1. 개체 선언2014년 10월 20일 웨이백 머신에 보관:
"예약된 단어 상수가 개체 선언에 나타나는 경우 선언된 개체는 상수로서, 선언문에 명시적인 초기화가 포함되어야 한다. 초기화 후에는 상수 값을 수정할 수 없다. 하위 프로그램 및 항목에서 모드의 공식 파라미터와 일반 형식 파라미터도 상수, 루프 파라미터는 해당 루프 내의 상수, 상수의 하위 구성요소 또는 슬라이스는 상수"라고 말했다. - ^ "const". MDN. Retrieved 31 October 2017.
외부 링크
- 허브 서터의 "Const-Correctness"
- 허브 서터의 "Constant Optimization?"
- C++ FAQ Lite: Marshall Cline의 정확성
- Bruce Eckel의 C++ 무료 전자책의 "가치 대체" 섹션
- 월터 브라이트의 "Here A Const, There A Const"
- D 프로그래밍 언어 규격의 "Const and Invariant" 버전 2(실험)