编译器不能自己判断一个变量是否为const吗?

Can the compiler not determine whether a variable is const by Itself?

我知道对于这么简单的函数,它将被内联:

int foo(int a, int b){
    return a + b;
}

但我的问题是,编译器不能自动检测这与以下内容相同:

int foo(const int a, const int b){
    return a + b;
}

既然可以检测到,为什么我需要在任何地方输入 const?我知道 inline 关键字由于编译器的进步而变得过时了。 const 是时候做同样的事情了吗?

can't the compiler just auto-detect that this is the same as...

如果你的意思是编译器是否可以检测到变量在第二种情况下没有被修改,很可能是。编译器可能会为两个代码示例生成相同的输出。但是,const 可能会在更复杂的情况下帮助编译器。但最重要的一点是,它可以防止 无意中修改其中一个变量。

也许他可以,但是 const 语句也适用于 you。如果您将变量设置为 const 并尝试在之后分配一个新值,您将收到错误消息。如果编译器自己从中生成一个 var,这是行不通的。

你没有把 const 作为不修改变量的结果。您使用 const 强制 您不修改它。如果没有const,您可以修改该值。使用 const,编译器会报错。

这是语义问题。如果该值不应该是可变的,则使用 const,编译器将强制执行该意图。

简短回答:因为并非所有问题都那么简单。

更长的答案:您不能假设适用于简单问题的方法也适用于复杂问题

正确答案:const 是一个意图。 const 的主要目标是防止你不小心做任何事情。如果编译器会自动添加 const,它只会看到该方法不是 const 并将其保留。使用 const 关键字将引发错误。

Const 限定符是一种强制执行范围内变量行为的方法。如果您尝试在声明为 const 的范围内修改它们,它只会为编译器提供向您尖叫的方法。

如果变量在声明时是常量,则它可能是真正的常量(意味着它被写入只读位置,因此编译器优化)。

您可以提供第二个函数非 const 变量,这些变量将在函数作用域内变为 "const"。

或者您可以通过强制转换绕过 const,这样编译器就无法解析您的整个代码以试图确定 valuea 是否会在函数范围内更改。

考虑到 const 限定符主要用于代码强制执行,如果变量是 const 或非 const,编译器将在 99% 的情况下生成相同的代码,那么 NO,编译器不应该自动检测常量。

编译器将始终知道您做了什么,并会从中推断出内部常量以优化代码。

编译器永远知道的是您想要做的

如果您想要一个变量保持不变但后来在代码中不小心更改了它,编译器只能在您告诉编译器您想要.

这就是 const 关键字的用途。

struct bar {
  const int* x;
};

bar make_bar(const int& x){
  return {&x};
}

std::map<int,bar> data;

shuffle(data);

知道 bar 在其生命周期内永远不会修改 x(或导致它被修改)需要了解程序中对 bar 的每次使用,或者说,使x 指向 const.

的指针

即使有完美的整个程序优化(不可能存在:图灵机不是完全可以理解的),动态链接意味着您无法在编译时知道数据将如何使用。 const 是一个承诺,违反该承诺(在某些情况下)可能是 UB。编译器可以使用该 UB 以忽略被破坏的承诺的方式进行优化。

inline 并没有过时:它的意思和它曾经做过的一样,这个符号的链接器冲突将被忽略,它温和地建议将代码注入调用范围。

const 简化了某些优化(这可能使它们成为可能),并对程序员强制执行(这有助于程序员),并且可以改变代码的含义(const 重载)。

是的,编译器可以在您的示例中证明常量。

不,没有用:-)。

更新: 赫伯·萨特 (Herb Sutter) 将他的陷阱之一专门用于该主题 (http://www.gotw.ca/gotw/081.htm)。摘要:

  • const 通过使编译器和链接器为 const 对象选择函数(包括 const 成员函数,可以将其编码为更高效)来提供最大帮助。
  • const 对通常的翻译单元模型没有帮助[与我的假设不同];编译器需要查看整个程序以验证事实常量性(仅仅声明不能保证)并利用它,以及证明不存在别名...
  • ...和编译器可以看到整个程序并且可以证明事实上的常量性它实际上当然不再需要常量声明! 可以证明。呸
  • const 最重要的一个地方是定义,因为编译器可能会将对象存储在只读内存中。

这篇文章当然值得一读。

关于整个程序 optimization/translation 这通常是利用 constness cf 所必需的。以下评论来自 amdn 和 Angew。