我找不到太多关于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
的情况下才是安全的。例如,如果你有一个函数,其参数为const char *
,而你传入了一个可修改的char *
,那么将该参数重新转换为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
§7.1.5.1/4
说道:“除了任何声明为mutable (7.1.1)的类成员可以被修改之外,在其生命周期内试图修改const对象都会导致未定义行为。” 任何尝试!没有提到原始变量的任何字眼。 - Alexey Malistovconst_cast
从最初声明为const
的对象中去除const
并不属于未定义行为。但是,实际尝试写入该对象将导致未定义行为。只要你只是读取该对象,那么你就没有问题,const_cast
本身并不会引起未定义行为。这是一个可怕的想法,但它本身并不会导致未定义行为。 - Jesper Juhl我可以想到两种情况下const_cast是安全和有用的(可能还有其他有效的情况)。
一种情况是当您有一个常量实例、引用或指针,并且您想要传递一个指向不符合const规定的API的指针或引用,但您确定该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()));
}
另一种情况是如果您使用的是不支持'mutable'的旧编译器,并且您想创建一个在逻辑上是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
是否会导致未定义的行为,而不是它有什么有用的应用。 - Michael Mrozekconst_cast
的示例用法是一个有效的答案。问题中没有“他”,因为问题本身就是主语。 - daparic我很难相信这是你能在const_cast上找到的唯一信息。引用自第二个Google搜索结果:
如果你强制转换一个明确声明为常量的对象,并试图修改它,结果是未定义的。
然而,如果你强制转换一个未经显式声明为常量的对象的常量性,你可以安全地修改它。
const_cast
。或调用一个const方法。 - Rob KennedyAdam说的话。另一个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;
};
this
指向的内容添加 const,然后调用 getT
的 const 版本,最后我们从返回值类型中删除 const,由于 t
必须是非 const 的(否则就不能调用非 const 版本的 getT
),这是有效的。如果您有一个庞大的函数体并且想要避免冗余代码,则此方法非常有用。const_cast
和static_cast
哪个更好一直有不同的看法。const_cast
只能做你想要的事情:改变cv限定符。而static_cast
则可能会“默默地”执行其他你不打算进行的操作。然而,第一个转换完全是安全的,static_cast
通常比const_cast
更安全。我认为这是一个场景,const_cast
更能表达你的意图,但static_cast
更能传达你的行动安全性。 - David Stone简短回答是不安全的。
长话短说,如果您足够了解如何使用,则应该是安全的。
当您进行类型转换时,实际上是在说:“我知道编译器不知道的东西。”在const_cast的情况下,您要表达的是:“即使这个方法接受一个非const的引用或指针,我知道它不会改变我传递的参数。”
因此,如果您确实知道自己在使用转换时所声称的内容,那么使用它是可以的。
如果您开始修改编译器认为是常量的内容,那么您将破坏线程安全性的任何可能性。
const
是信任。const_cast
则破坏了这种信任:( - bobobobo
const
属性的引用/指针来修改原始的“const”对象时,它才会变得不安全。如果相反,你只是使用const_cast
来解决一个API规范(在我这种情况下是懒散的)只接受非“const”引用但仅将在“const”方法中使用的问题…那就没有任何问题。 - underscore_d