只要未实际修改const定义的对象,是否可以将其抛弃?

时间:2019-02-03 15:11:18

标签: c++ const undefined-behavior const-cast

是否允许以下​​内容:

const int const_array[] = { 42 };

int maybe_inc(bool write, int* array) {
  if (write) array[0]++;
  return array[0];
}

int main() {
  return maybe_inc(false, const_cast<int *>(const_array));
}

特别是,只要示例中没有实际修改对象,就可以放弃{<1>}定义为常量的const_array的常量性吗?

2 个答案:

答案 0 :(得分:10)

是的。这是完全合法的。 (这很危险,但是它是合法的。)如果(尝试)修改一个声明为const的对象,则行为是不确定的。

摘自n4659(这是C ++ 17的最新草案),第10.1.7.1节[dcl.type.cv]第4段:

  

除了可以声明任何声明为可变的类成员(10.1.1)之外,任何在其生存期(6.8)内修改const对象的尝试都会导致未定义的行为

我的重点。那是从C ++ 17开始的,但是对于所有版本的C ++都是如此。

如果您查看const_cast上的部分,请注意

  

[注意:根据对象的类型,通过指针,左值或指针进行写操作   丢弃const-qualifier76的const_cast生成的数据成员可能会产生未定义的   行为(10.1.7.1)。 —尾注]

注释不是规范性的,但这强烈意味着获得非const引用或指向const对象的指针是合法的。不允许写。

答案 1 :(得分:-2)

如果编译,则允许它。但这并不意味着它是合法的。

#include <iostream>

int main(int argc, char *argv[]) 
{
    const int arr[] = {1, 2, 3};
    int* parr = const_cast<int*>(arr);
    parr[0] = 0;
    for(auto& n : arr)
        std::cout << n << std::endl;
}

以上代码在Ubuntu 20.04 g++编译器中编译。它也可以毫无问题地运行。但是上面的代码实际上是未定义的行为