c++ - const 参数 "real"是常量吗?

标签 c++

AFAIK 从 const 变量中删除 constness 是未定义的行为:

const int i = 13;
const_cast<int&>(i) = 42;      //UB
std::cout << i << std::endl;   //out: 13

但是 const 函数参数是“真正的”常量吗?让我们考虑以下示例:

void foo(const int k){
    const_cast<int&>(k) = 42;    //UB?
    std::cout << k << std::endl;
}

int main(){
    foo(13); //out: 42
}

似乎编译器没有对 const int k 应用与 const int i 相同的优化。

第二个例子有UB吗? const int k 是帮助编译器优化代码,还是编译器只检查 const 的正确性,仅此而已?

Example

最佳答案

const int i = 13; 中的 i 可以用作常量表达式(作为模板参数或 case 标签)并且尝试修改它是未定义的行为。这是为了向后兼容没有 constexpr 的 C++11 之前的代码。

声明 void foo(const int k);void foo(int k); 声明相同的函数;参数的顶级 const 不参与函数的签名。参数 k 必须按值传递,因此不能是“真正的”常量。抛弃它的常量并不是未定义的行为。 编辑:但是任何修改它的尝试仍然是未定义的,因为它是 const object [basic.type.qualifier] (1.1):

A const object is an object of type const T or a non-mutable subobject of such an object.

通过[dcl.type.cv] 4 const object cannot be modified:

Except that any class member declared mutable (10.1.1) can be modified, any attempt to modify a const object during its lifetime (6.8) results in undefined behavior.

并且由于函数参数具有自动存储持续时间,因此无法通过 [basic.life] 10 也创建其存储中的新对象:

Creating a new object within the storage that a const complete object with static, thread, or automatic storage duration occupies, or within the storage that such a const object used to occupy before its lifetime ended, results in undefined behavior.

不清楚为什么 k 被声明为 const 如果有计划放弃它的常量?它的唯一目的感觉是混淆和混淆。

一般来说,我们应该在任何地方都支持不变性,因为它可以帮助人们进行推理。它还可以帮助编译器进行优化。然而,在我们只声明不变性但不尊重它的地方,它会起到相反的作用并造成混淆。

我们应该支持的另一件事是纯函数。这些不依赖于或修改任何外部状态并且没有副作用。这些也更容易为人们和编译器推理和优化。目前,此类函数可以声明为 constexpr。然而,即使在 constexpr 函数的上下文中,将按值参数声明为 const 也无助于任何优化。

关于c++ - const 参数 "real"是常量吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52754501/

相关文章:

c++ - 使用 libxml 解析 xml 文件时删除注释

c++ - FFmpeg - RTCP BYE 数据包

c++ - ActiveX 属性(从 Visual Basic 访问)是否可以在运行时按程序生成?

c++ - 将 `std::addressof` 和 `operator&` 一起介绍给学生会有什么缺点吗?

c++ - 需要将一行中的数字与字符串分开,在C++中用 ';'(25; 16; 67; 13)分隔

c++ - 碱基转换问题

java - 鸭子类型(duck typing)和泛型编程

c++ - `std::istream::operator>>()` 可以接受像 stdio 的 %i 格式说明符这样的整数基数前缀吗?

c++ - 为什么构造函数需要完全按照类命名?

c# - 使用 FreeImage 是否可以在 ARGB32 或 RGBA32 而不是 BGRA32 中输出 ConvertToRawBits?