是否允许以下情况:
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));
}
特别是,可以抛弃const_array
的constness吗?它被 * 定义 * 为const,只要对象没有被实际修改,就像示例中那样。
2条答案
按热度按时间noj0wjuj1#
是的。这是完全法律的的。(这是危险的,但它是合法的。)如果你(试图)修改一个声明为常量的对象,那么行为是未定义的。
来自n4659(C17的最后一个草稿),10.1.7.1dcl.type.cv]部分第4段:
除了声明为mutable(10.1.1)的任何类成员都可以修改之外,在const对象的生存期(6.8)内修改该对象的任何尝试都将导致未定义的行为
我强调的是,这是从C17开始的,但这对所有版本的C都是如此。
如果您查看有关
const_cast
的部分,会发现[注:根据对象的类型,通过指针、左值或指针指向const_cast(丢弃常量限定符76)产生的数据成员的写操作可能会产生未定义的行为(10.1.7.1)。- end note ]
注解并不规范,但这强烈暗示了获取一个非常量的引用或指向常量对象的指针是法律的的,而写是不允许的。
C20的新参考:
来自N4680(C++20的最后一个草案),9.2.8.1dcl.type.cv]部分第4段:
在7.6.1.57.6.2.2const对象(6.8.3)的生存期(6.7.3)内,任何修改(7.6.19、www.example.com、www.example.com)该对象的尝试都会导致未定义的行为。
如果您查看有关
const_cast
的部分,7.6.1.10[expr.const.cast]第6段,链接到上述声明:[Note:根据对象的类型,通过指针、左值或指针指向const_cast(丢弃常量限定符)生成的数据成员的写操作可能会产生未定义的行为(9.2.8.1)。]
ctehm74n2#
下面的代码编译并运行,输出如下。我可以 override
arr
的 * constability *,事实上,修改第一个元素成为0
:上面的代码在Ubuntu 20.04
g++
编译器和Visual Studio C++中编译。它运行起来也没有问题。但上面的代码实际上是未定义的行为。它的输出: