const_cast安全吗?

Mag*_*der 88 c++ casting const-cast

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

const_cast<>()用于添加/删除变量的常量(岬)(或挥发性岬).

这让我很紧张.可能const_cast会导致意外行为?如果是这样,什么?

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

Ada*_*eld 86

const_cast只有在您投射最初非变量的变量时才是安全的const.例如,如果你有一个带a参数的函数const char *,并传入一个可修改的函数,那么该参数char *可以安全地const_cast返回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
Run Code Online (Sandbox Code Playgroud)

  • @Alexey Malistov:不."对象"是指内存中占用的实际存储区域(§1.7).对非const对象进行const引用不会使对象成为常量.只有在const**引用**参数(*not*a const pointer parameter)的情况下才允许编译器静默地复制(§5.2.2/ 5); 这不是这里的情况. (42认同)
  • @Alexey:原始变量是关于指向或引用的内容.您可以对非const对象进行const引用,因此,将其转换为可写引用是明确定义的行为,因为引用的对象实际上不是const. (20认同)
  • 这不是真的.C++标准.`§7.1.5.1/ 4说除了可以修改任何声明可变的类成员(7.1.1),任何在其生命周期内修改const对象的尝试(3.8)都会导致未定义的行为.**任何尝试**!没有关于原始变量的文字. (9认同)
  • _"但是,如果原始变量实际上是const,那么使用const_cast将导致未定义的行为"_此语句为false. (5认同)
  • 使用`const_cast`从最初声明为`const`的东西中删除`const`是*不是*UB.但它实际上是尝试写入该对象的*UB.只要你刚读完就好了,`const_cast`本身不会导致UB.这是一个可怕的想法,但它本身并不是UB. (4认同)
  • @DarkFalcon看到这句话:`只有在const引用参数(不是const指针参数)的情况下才允许编译器从他的注释中默默地复制(第5.2.2/5节). (3认同)
  • 文字是唯一最初声明为const的数据吗? (2认同)

Fre*_*son 34

我可以想到const_cast安全且有用的两种情况(可能还有其他有效的情况).

一种是当你有一个const实例,引用或指针,并且你想要将指针或引用传递给不是const-correct的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()));
}
Run Code Online (Sandbox Code Playgroud)

另一种情况是,如果您使用的是未实现'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];
    }
};
Run Code Online (Sandbox Code Playgroud)

  • 从问题:"或者,什么时候可以使用const_cast?" (13认同)
  • 我们只能坚持问题的字母。基于此,给出“const_cast”的说明性使用是一个有效的答案。问题中没有“他”,因为问题本身就是主语。 (2认同)

Rob*_*edy 22

我发现很难相信这是你能找到的关于const_cast 的唯一信息.引用第二个Google热门话题:

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

但是,如果丢弃未明确声明为const的对象的常量,则可以安全地修改它.


Joh*_*itb 11

亚当说的话.另一个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;
};
Run Code Online (Sandbox Code Playgroud)

我们首先将const添加到类型this点,然后我们调用const版本getT,然后我们从返回类型中删除const,这是有效的,因为t必须是非const(否则,非const版本getT不能有被称为).如果您有一个大型函数体并且想要避免冗余代码,这可能非常有用.

  • 我宁愿使用static强制转换来添加constness:static_cast &lt;const sample *&gt;(this)。当我阅读const_cast时,它意味着代码正在做潜在危险的事情,因此我尝试避免在可能的情况下使用它。 (2认同)
  • 我会来回询问`const_cast`或`static_cast`是否更好.`const_cast`只能做你想要的:更改cv限定符.`static_cast`可以'静默'执行你不想要的其他操作.但是,第一次演员是完全安全的,`static_cast`往往比`const_cast`更安全.我认为这是'const_cast`更好地传达你的意图的情况,但是`static_cast`可以更好地传达你行动的安全性. (2认同)

Joh*_*McG 9

简短的回答是不,这不安全.

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

当你在施法时,你基本上说的是,"我知道编译器不知道的东西." 在const_cast的情况下,你所说的是,"即使这个方法接受一个非const引用或指针,我知道它不会改变我传递它的参数."

因此,如果您确实知道在使用演员表时您声称知道的内容,那么可以使用它.


Mat*_*ank 5

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

  • Const肯定是使代码线程安全的有用工具,但它没有保证(除了编译时常量).两个例子:一个const对象可能有可变成员,并且有一个指向对象的const指针没有说明对象本身是否可以改变. (6认同)