95

我找不到太多关于const_cast. 我能找到的唯一信息(在 Stack Overflow 上)是:

const_cast<>()用于添加/删除变量的 const(ness)(或 volatile-ness)。

这让我很紧张。可以使用const_cast导致意外行为吗?如果是这样,是什么?

或者,什么时候可以使用const_cast

4

6 回答 6

93

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
于 2008-12-10T21:04:30.760 回答
36

我可以想到 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];
    }
};
于 2008-12-10T21:25:59.263 回答
25

我很难相信这是你能找到的关于 const_cast的唯一信息。引用Google 的第二次点击

如果您抛弃已显式声明为 const 的对象的 const 性,并尝试修改它,则结果是未定义的。

然而,如果你抛弃了一个没有显式声明为 const 的对象的 const 性,你可以安全地修改它。

于 2008-12-10T21:10:29.310 回答
13

亚当所说的。另一个 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不能有被调用)。如果你有一个大的函数体并且你想避免冗余代码,这将非常有用。

于 2008-12-10T21:17:48.983 回答
10

简短的回答是否定的,它不安全。

长答案是,如果你知道足够使用它,那么它应该是安全的。

当你进行强制转换时,你实际上是在说,“我知道一些编译器不知道的东西。” 在 const_cast 的情况下,您要说的是,“即使此方法接受非 const 引用或指针,我知道它不会更改我传递给它的参数。”

因此,如果您确实知道在使用演员表时声称知道什么,那么使用它就可以了。

于 2008-12-10T22:39:53.047 回答
3

如果你开始修改编译器认为是 const 的东西,你就会破坏线程安全的任何机会。

于 2008-12-10T21:16:37.100 回答