문제
많은 정보를 찾을 수 없습니다 const_cast
. 내가 찾을 수있는 유일한 정보 (스택 오버플로에서)는 다음과 같습니다.
그만큼
const_cast<>()
변수의 const (또는 휘발성)를 추가/제거하는 데 사용됩니다.
이것은 나를 긴장하게 만듭니다. a를 사용할 수 있습니다 const_cast
예상치 못한 행동을 일으키나요? 그렇다면 무엇입니까?
또는 언제 사용해도 괜찮습니까? const_cast
?
해결책
const_cast
원래가 아닌 변수를 캐스팅하는 경우에만 안전합니다.const
. 예를 들어, 매개 변수를 사용하는 함수가있는 경우 const char *
, 그리고 당신은 수정 가능한 것을 통과합니다 char *
, 안전합니다 const_cast
해당 매개 변수는 a로 돌아갑니다 char *
그리고 그것을 수정하십시오. 그러나 원래 변수가 실제로 인 경우 const
, 그런 다음 사용합니다 const_cast
정의되지 않은 동작이 발생합니다.
void func(const char *param, size_t sz, bool modify)
{
if(modify)
strncpy(const_cast<char *>(param), sz, "new string");
printf("param: %s\n", param);
}
...
char buffer[16];
const char *unmodifiable = "string constant";
func(buffer, sizeof(buffer), true); // OK
func(unmodifiable, strlen(unmodifiable), false); // OK
func(unmodifiable, strlen(unmodifiable), true); // UNDEFINED BEHAVIOR
다른 팁
Const_cast가 안전하고 유용한 두 가지 상황을 생각할 수 있습니다 (다른 유효한 경우가있을 수 있음).
하나는 const 인스턴스, 참조 또는 포인터가있을 때, const-correct가 아닌 API에 대한 포인터 또는 참조를 전달하려고하지만 객체를 수정하지는 않을 것입니다. 당신은 pointer를 const_cast하고 그것을 API로 전달할 수 있습니다. 예를 들어:
void log(char* text); // Won't change text -- just const-incorrect
void my_func(const std::string& message)
{
log(const_cast<char*>(&message.c_str()));
}
다른 하나는 'Mutable'을 구현하지 않는 이전 컴파일러를 사용하는 경우 논리적으로 const이지만 약간의 const가 아닌 클래스를 만들고자하는 것입니다. Const_cast 'this'를 const 메소드 내에서 const_cast하고 클래스 멤버를 수정할 수 있습니다.
class MyClass
{
char cached_data[10000]; // should be mutable
bool cache_dirty; // should also be mutable
public:
char getData(int index) const
{
if (cache_dirty)
{
MyClass* thisptr = const_cast<MyClass*>(this);
update_cache(thisptr->cached_data);
}
return cached_data[index];
}
};
나는 그것이 뿐 const_cast에 대해 찾을 수있는 정보. 인용 두 번째 구글 히트:
명시 적으로 const로 선언 된 물체의 콘트니스를 캐스트하고 수정하려고 시도하면 결과가 정의되지 않습니다.
그러나 명시 적으로 const로 선언되지 않은 물체의 콘트 스네스를 캐스트하면 안전하게 수정할 수 있습니다.
아담이 말하는 것. const_cast가 도움이 될 수있는 또 다른 예 :
struct sample {
T& getT() {
return const_cast<T&>(static_cast<const sample*>(this)->getT());
}
const T& getT() const {
/* possibly much code here */
return t;
}
T t;
};
우리는 먼저 유형에 const를 추가합니다 this
포인트, 우리는 Const 버전을 호출합니다. getT
, 그리고 우리는 반환 유형에서 const를 제거합니다. t
비 초가적이어야합니다 (그렇지 않으면, 비 초가 버전은 getT
호출 할 수 없었습니다). 큰 기능 본문을 가지고 있고 중복 코드를 피하려면 매우 유용 할 수 있습니다.
짧은 대답은 아니오입니다. 안전하지 않습니다.
긴 대답은 사용하기에 충분히 알고 있다면 안전해야한다는 것입니다.
캐스팅을 할 때 본질적으로 말하는 것은 "컴파일러가 모르는 것을 알고 있습니다." const_cast의 경우, 당신이 말하는 것은 "이 방법이 비 초회적 참조 또는 포인터를 사용하더라도 전달한 매개 변수를 변경하지 않는다는 것을 알고 있습니다."
따라서 캐스트를 사용할 때 알고 있다고 주장하는 것을 실제로 알고 있다면 사용하는 것이 좋습니다.
컴파일러 생각이 const라고 생각한 것을 수정하기 시작하면 스레드 안전에서 기회를 파괴하고 있습니다.
#include <iostream>
using namespace std;
void f(int* p) {
cout << *p << endl;
}
int main(void) {
const int a = 10;
const int* b = &a;
// Function f() expects int*, not const int*
// f(b);
int* c = const_cast<int*>(b);
f(c);
// Lvalue is const
// *b = 20;
// Undefined behavior
// *c = 30;
int a1 = 40;
const int* b1 = &a1;
int* c1 = const_cast<int*>(b1);
// Integer a1, the object referred to by c1, has
// not been declared const
*c1 = 50;
return 0;
}