我找不到太多关于const_cast
. 我能找到的唯一信息(在 Stack Overflow 上)是:
const_cast<>()
用于添加/删除变量的 const(ness)(或 volatile-ness)。
这让我很紧张。可以使用const_cast
导致意外行为吗?如果是这样,是什么?
或者,什么时候可以使用const_cast
?
我找不到太多关于const_cast
. 我能找到的唯一信息(在 Stack Overflow 上)是:
const_cast<>()
用于添加/删除变量的 const(ness)(或 volatile-ness)。
这让我很紧张。可以使用const_cast
导致意外行为吗?如果是这样,是什么?
或者,什么时候可以使用const_cast
?
const_cast
仅当您正在转换一个最初不是的变量时才是安全的const
。例如,如果您有一个接受 a 参数的函数const char *
,并且您传入一个 modifiable char *
,那么const_cast
将该参数返回给 achar *
并对其进行修改是安全的。但是,如果原始变量实际上是const
,那么 usingconst_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 实例、引用或指针,并且您想将指针或引用传递给不正确的 API,但您确定不会修改该对象。您可以 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()));
}
另一种情况是,如果您使用的是未实现“可变”的旧编译器,并且您想创建一个逻辑上为 const 但不是按位 const 的类。您可以在 const 方法中 const_cast 'this' 并修改类的成员。
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的唯一信息。引用Google 的第二次点击:
如果您抛弃已显式声明为 const 的对象的 const 性,并尝试修改它,则结果是未定义的。
然而,如果你抛弃了一个没有显式声明为 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 引用或指针,我知道它不会更改我传递给它的参数。”
因此,如果您确实知道在使用演员表时声称知道什么,那么使用它就可以了。
如果你开始修改编译器认为是 const 的东西,你就会破坏线程安全的任何机会。