6

在 C++ 中,我有一个只需要对数组进行只读访问但被错误地声明为接收非常量指针的函数:

size_t countZeroes( int* array, size_t count )
{
    size_t result = 0;        
    for( size_t i = 0; i < count; i++ ) {
       if( array[i] == 0 ) {
           ++result;
       }
    }
    return result;
}

我需要为 const 数组调用它:

static const int Array[] = { 10, 20, 0, 2};

countZeroes( const_cast<int*>( Array ), sizeof( Array ) / sizeof( Array[0] ) );

这将是未定义的行为吗?如果是这样 - 程序何时会运行到 UB - 当执行 const_cast 并调用函数或访问数组时?

4

5 回答 5

14

是的,这是允许的(如果危险!)。const这是对导致未定义行为的对象的实际写入,而不是转换本身(7.1.5.1/4 [dcl.type.cv])。

正如 5.2.11/7 [expr.const.cast] 中的标准注释,根据对象的类型,尝试通过作为丢弃结果的指针写入const可能会产生未定义的行为。

于 2009-10-09T07:15:34.690 回答
1

由于您的代码没有修改数组,并且您告诉编译器您知道自己在做什么const_cast,因此您实际上会没事的。但是,我相信您在技术上调用了未定义的行为。最好修复函数声明,或者编写、声明和使用它的 const 安全版本。

于 2009-10-09T07:02:51.227 回答
1

是的,你可以这么做。不,只要函数确实不尝试写入数组,它就不是未定义的行为。

于 2009-10-09T18:22:20.200 回答
1

的问题const_cast总是一样的——它允许你“打破规则”,就像强制转换一样void*——当然你可以这样做,但问题是你为什么要这样做?

在这种情况下当然可以,但是您应该问自己为什么不首先声明size_t countZeroes( const int* array, size_t count )

作为一般规则const_cast

  1. 它可能会产生难以发现的错误
  2. 您正在丢弃与编译器的 const 协议
  3. 基本上,您正在将语言转换为较低级别的语言。
于 2009-12-19T01:51:47.260 回答
-2

const_cast在最初定义为 UB 的对象上使用const,因此未定义的行为会在您调用const_cast.

于 2009-10-09T07:02:26.097 回答