我知道对于这么简单的函数,它将被内联:
int foo(int a, int b){
return a + b;
}
但我的问题是,编译器不能自动检测到这与以下内容相同:
int foo(const int a, const int b){
return a + b;
}
既然可以检测到,为什么我需要在const
任何地方输入?我知道inline
由于编译器的进步,关键字已经过时了。不是时候const
做同样的事情了吗?
我知道对于这么简单的函数,它将被内联:
int foo(int a, int b){
return a + b;
}
但我的问题是,编译器不能自动检测到这与以下内容相同:
int foo(const int a, const int b){
return a + b;
}
既然可以检测到,为什么我需要在const
任何地方输入?我知道inline
由于编译器的进步,关键字已经过时了。不是时候const
做同样的事情了吗?
你不把const
作为不修改变量的结果。你const
用来强制你不修改它。没有const
,您可以修改该值。使用const
,编译器会抱怨。
这是语义问题。如果该值不应该是可变的,则使用const
,编译器将强制执行该意图。
是的,编译器可以在您的示例中证明 constness。
不,这没有用:-)。
更新: Herb Sutter 将他的一个陷阱专门用于该主题(http://www.gotw.ca/gotw/081.htm)。概括:
这篇文章当然值得一读。
关于整个程序优化/翻译,这通常是利用 constness 所必需的,参见。以下来自 amdn 和 Angew 的评论。
编译器不能自动检测到这与...相同吗?
如果你的意思是编译器是否可以检测到变量在第二种情况下没有被修改,很可能是的。编译器可能会为两个代码示例生成相同的输出。但是,const
在更复杂的情况下可能会帮助编译器。但最重要的一点是,它可以防止您无意中修改其中一个变量。
编译器将始终知道您做了什么,并从中推断出内部常量以优化代码。
编译器永远无法知道您想要做什么。
如果您希望变量保持不变,但后来在代码中意外更改它,编译器只能在您告诉编译器您想要什么时捕获此错误。
这就是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
重载)。
也许他可以,但const语句也适合你。如果您将变量设置为 const 并在之后尝试分配新值,则会出现错误。如果编译器自己制作一个 var ,这是行不通的。
const 限定符是一种在你的范围内强制执行变量行为的方法。如果您尝试在声明为 const 的范围内修改它们,它只会为编译器提供向您尖叫的方法。
如果变量在声明时为 const,则它可能是真正的 const (意味着它被写入只读位置,因此编译器优化)。
您可以提供第二个函数非常量变量,这些变量将在函数范围内变为“const”。
或者,您可以通过 cast 绕过 const ,因此编译器无法解析您的整个代码以试图确定 valuea 是否会在函数范围内更改。
考虑到 const 限定符主要用于代码强制,并且如果变量是 const 或非 const,编译器将在 99% 的情况下生成相同的代码,那么不,编译器不应该自动检测 constness。
简短的回答:因为并非所有问题都那么简单。
更长的答案:您不能假设适用于简单问题的方法也适用于复杂问题
确切答案: const 是一个意图。const 的主要目标是防止您意外地做任何事情。如果编译器会自动添加 const 它只会看到该方法不是 const 并将其保留。使用 const 关键字将引发错误。