const_cast
conversion
서로 다른 cv 한정자를 가진 타입 간 변환을 수행합니다.
목차 |
구문
const_cast<
target-type
>(
expression
)
|
|||||||||
target-type 타입의 값을 반환합니다.
설명
다음 변환만 const_cast 로 수행할 수 있습니다:
T1
과
T2
에 대해,
T1
타입의 prvalue는
T1
과
T2
가 오직 cv-qualification만 다를 경우(공식적으로, 두 타입의
qualification-decompositions
를 고려했을 때, 모든
i
에 대해 각
P1_i
가
P2_i
와 동일한 경우)
T2
로 변환될 수 있습니다.
- 만약 expression 이 null 포인터 값이면, 결과 또한 null 포인터 값입니다.
- 만약 expression 이 null 멤버 포인터 값이면, 결과 또한 null 멤버 포인터 값입니다.
- 만약 expression 이 객체를 가리키면, 결과는 동일한 객체를 가리킵니다.
- 만약 expression 이 객체의 끝을 지나서 가리키면, 결과는 동일한 객체의 끝을 지나서 가리킵니다.
- 만약 expression 이 데이터 멤버를 가리키면, 결과는 동일한 데이터 멤버를 가리킵니다.
|
expression 이 prvalue인 경우에도, temporary materialization 은 수행되지 않습니다. |
(C++17부터) |
T1
과
T2
에 대해,
T1
에 대한 포인터가
const_cast
<
T2
*
>
를 사용하여 "pointer to
T2
" 타입으로 명시적으로 변환될 수 있다면, 다음 변환들도 수행될 수 있습니다:
-
T1타입의 lvalue는 const_cast < T2 & > 를 사용하여T2타입의 lvalue로 명시적으로 변환될 수 있습니다.
|
(C++11부터) |
|
결과 참조는 원본 객체를 참조합니다. |
(C++17까지) |
|
표현식 이 glvalue인 경우, 결과 참조는 원본 객체를 참조합니다. 그렇지 않으면, 결과 참조는 구체화된 임시 객체 를 참조합니다. |
(C++17부터) |
모든 형변환 표현식과 마찬가지로, 결과는 다음과 같습니다:
- target-type 이 lvalue 참조 타입인 경우 lvalue 또는 함수 타입에 대한 rvalue 참조인 경우 (C++11부터) ;
|
(since C++11) |
- 그렇지 않으면 prvalue입니다.
const 제거 캐스팅
서로 다른 두 타입
T1
과
T2
에 대해,
T1
에서
T2
로의 변환이
constness를 제거한다
는 것은,
T2
의
자격 분해
가 "cv2_0 P2_0 cv2_1 P2_1 ... cv2_n−1 P2_n−1 cv2_n U2" 형태로 존재하고,
T1
을 "cv2_0 P1_0 cv2_1 P1_1 ... cv2_n−1 P1_n−1 cv2_n U1"로 변환하는
자격 변환
이 존재하지 않는 경우를 말합니다 (동일한 cv 구성 요소, 다른 P 구성 요소 및 U 구성 요소).
만약
T1*
타입의 prvalue에서
T2*
타입으로의 캐스트가 constness를 제거한다면,
T1
타입의 표현식에서
T2
에 대한 참조로의 캐스트도 constness를 제거하게 됩니다.
오직 const_cast 만이 constness를 제거하는 데 사용될 수 있습니다.
"constness를 없애는 캐스팅"은 "volatility를 없애는 캐스팅"을 의미합니다. 왜냐하면 한정 변환(qualification conversion)은 volatility 역시 없앨 수 없기 때문입니다.
참고 사항
함수에 대한 포인터와 멤버 함수에 대한 포인터는 const_cast 의 적용 대상이 아닙니다.
const_cast 는 실제로 const 객체 를 참조하는 비-const 타입의 참조자나 포인터를 형성하거나, 실제로 volatile 객체 를 참조하는 비-volatile 타입의 참조자나 포인터를 형성할 수 있게 합니다. const 객체를 비-const 접근 경로를 통해 수정하거나 volatile 객체를 비-volatile glvalue 를 통해 참조하는 것은 정의되지 않은 행동을 초래합니다.
키워드
예제
#include <iostream> struct type { int i; type(): i(3) {} void f(int v) const { // this->i = v; // 컴파일 오류: this는 const에 대한 포인터입니다 const_cast<type*>(this)->i = v; // type 객체가 const가 아닌 경우 OK } }; int main() { int i = 3; // i는 const로 선언되지 않음 const int& rci = i; const_cast<int&>(rci) = 4; // OK: i를 수정함 std::cout << "i = " << i << '\n'; type t; // 이게 const type t였다면 t.f(4)는 정의되지 않은 동작이 됨 t.f(4); std::cout << "type::i = " << t.i << '\n'; const int j = 3; // j는 const로 선언됨 [[maybe_unused]] int* pj = const_cast<int*>(&j); // *pj = 4; // 정의되지 않은 동작 [[maybe_unused]] void (type::* pmf)(int) const = &type::f; // 멤버 함수 포인터 // const_cast<void(type::*)(int)>(pmf); // 컴파일 오류: const_cast는 // 함수 포인터에서 작동하지 않음 }
출력:
i = 4 type::i = 4
결함 보고서
다음의 동작 변경 결함 보고서들은 이전에 발표된 C++ 표준에 소급 적용되었습니다.
| DR | 적용 대상 | 게시된 동작 | 올바른 동작 |
|---|---|---|---|
| CWG 1965 | C++11 | const_cast 가 배열 prvalue에 대한 rvalue 참조를 바인딩할 수 없었음 | 해당 참조 바인딩 허용 |
| CWG 2879 | C++17 | 포인터 pvalue 피연산자가 materialized되었음 | materialized되지 않음 |
참고문헌
- C++23 표준 (ISO/IEC 14882:2024):
-
- 7.6.1.11 Const cast [expr.const.cast]
- C++20 표준(ISO/IEC 14882:2020):
-
- 7.6.1.10 Const cast [expr.const.cast]
- C++17 표준 (ISO/IEC 14882:2017):
-
- 8.2.11 Const cast [expr.const.cast]
- C++14 표준(ISO/IEC 14882:2014):
-
- 5.2.11 Const cast [expr.const.cast]
- C++11 표준(ISO/IEC 14882:2011):
-
- 5.2.11 Const cast [expr.const.cast]
- C++98 표준 (ISO/IEC 14882:1998):
-
- 5.2.11 Const cast [expr.const.cast]
- C++03 표준 (ISO/IEC 14882:2003):
-
- 5.2.11 Const cast [expr.const.cast]