12

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

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

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

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

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

4

8 回答 8

19

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

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

于 2015-04-21T11:43:04.570 回答
13

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

不,这没有用:-)。

更新: Herb Sutter 将他的一个陷阱专门用于该主题(http://www.gotw.ca/gotw/081.htm)。概括:

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

这篇文章当然值得一读。

关于整个程序优化/翻译,这通常是利用 constness 所必需的,参见。以下来自 amdn 和 Angew 的评论。

于 2015-04-21T12:39:17.490 回答
9

编译器不能自动检测到这与...相同吗?

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

于 2015-04-21T11:41:57.490 回答
9

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

编译器永远无法知道您想要做什么

如果您希望变量保持不变,但后来在代码中意外更改它,编译器只能在您告诉编译器您想要什么时捕获此错误。

这就是const关键字的用途。

于 2015-04-21T12:03:41.260 回答
4
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重载)。

于 2015-04-21T12:18:33.670 回答
3

也许他可以,但const语句也适合。如果您将变量设置为 const 并在之后尝试分配新值,则会出现错误。如果编译器自己制作一个 var ,这是行不通的。

于 2015-04-21T11:42:47.490 回答
2

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

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

您可以提供第二个函数非常量变量,这些变量将在函数范围内变为“const”。

或者,您可以通过 cast 绕过 const ,因此编译器无法解析您的整个代码以试图确定 valuea 是否会在函数范围内更改。

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

于 2015-04-21T11:47:17.817 回答
0

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

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

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

于 2015-04-21T11:43:24.510 回答