- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
我知道它提高了可读性并减少了程序出错的可能性,但是它对性能的提高有多大?
顺便说一句,引用和 const
指针之间的主要区别是什么?我会假设它们以不同的方式存储在内存中,但如何呢?
最佳答案
[编辑:好的,所以这个问题比我一开始想的要微妙。]
声明指向 const 的指针或引用的 const 永远不会帮助任何编译器优化任何东西。 (尽管请参阅此答案底部的更新。)
const
声明仅指示标识符将如何在其声明的范围 内使用;它并不是说底层对象不能改变。
例子:
int foo(const int *p) {
int x = *p;
bar(x);
x = *p;
return x;
}
编译器不能假设 *p
没有被 bar()
的调用修改,因为 p
可能是(例如)一个指向全局 int 的指针,bar()
可能会修改它。
如果编译器足够了解 foo()
的调用者和 bar()
的内容,它可以证明 bar()
不修改 *p
,那么 它也可以在没有 const 声明的情况下执行该证明。
但这通常是正确的。因为 const
只在声明的范围内起作用,所以编译器已经可以看到您在该范围内如何处理指针或引用;它已经知道你没有修改底层对象。
所以简而言之,所有 const
在这种情况下所做的就是防止你犯错误。它不会告诉编译器任何它不知道的东西,因此它与优化无关。
调用 foo()
的函数呢?喜欢:
int x = 37;
foo(&x);
printf("%d\n", x);
编译器能否证明这打印出 37,因为 foo()
采用 const int *
?
没有。即使 foo()
采用指向 const 的指针,它也可能会丢弃 const 并修改 int。 (这不是未定义的行为。)在这里,编译器通常不能做出任何假设;如果它对 foo()
有足够的了解来进行这样的优化,它就会知道即使没有 const
。
const
唯一可能允许优化的情况是这样的:
const int x = 37;
foo(&x);
printf("%d\n", x);
在这里,通过任何机制修改 x
(例如,通过获取指向它的指针并丢弃 const
)就是调用未定义行为。所以编译器可以自由地假设你不这样做,它可以将常量 37 传播到 printf() 中。这种优化对于您声明 const
的任何对象都是合法的。 (实际上,您从不引用的局部变量不会受益,因为编译器已经可以看到您是否在其范围内对其进行了修改。)
要回答您的“旁注”问题,(a) const 指针是指针; (b) 一个 const 指针可以等于 NULL。您是正确的,内部表示(即地址)很可能是相同的。
[更新]
作为 Christoph在评论中指出,我的回答不完整,因为它没有提到 restrict
。
C99 标准的第 6.7.3.1 (4) 节说:
During each execution of B, let L be any lvalue that has &L based on P. If L is used to access the value of the object X that it designates, and X is also modified (by any means), then the following requirements apply: T shall not be const-qualified. ...
(这里 B 是一个基本 block ,P 是一个指向 T 的限制指针,在其范围内。)
所以如果一个 C 函数 foo()
是这样声明的:
foo(const int * restrict p)
...那么编译器可能假设在 p
的生命周期内不会对 *p
进行任何修改——即,在foo()
的执行——因为否则行为将是未定义的。
因此,原则上,将 restrict
与指向 const 的指针相结合可以启用上面忽略的两种优化。我想知道是否有任何编译器实际上实现了这样的优化? (至少 GCC 4.5.2 没有。)
请注意,restrict
仅存在于 C 中,而不存在于 C++(甚至 C++0x)中,除非是作为特定于编译器的扩展。
关于c++ - const-correctness 是否给编译器更多的优化空间?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6313730/
我有一个 if 语句,如下所示 if (not(fullpath.lower().endswith(".pdf")) or not (fullpath.lower().endswith(tup
然而,在 PHP 中,可以: only appears if $foo is true. only appears if $foo is false. 在 Javascript 中,能否在一个脚
XML有很多好处。它既是机器可读的,也是人类可读的,它具有标准化的格式,并且用途广泛。 它也有一些缺点。它是冗长的,不是传输大量数据的非常有效的方法。 XML最有用的方面之一是模式语言。使用模式,您可
由于长期使用 SQL2000,我并没有真正深入了解公用表表达式。 我给出的答案here (#4025380)和 here (#4018793)违背了潮流,因为他们没有使用 CTE。 我很欣赏它们对于递
我有一个应用程序: void deleteObj(id){ MyObj obj = getObjById(id); if (obj == null) { throw n
我的代码如下。可能我以类似的方式多次使用它,即简单地说,我正在以这种方式管理 session 和事务: List users= null; try{ sess
在开发J2EE Web应用程序时,我通常会按以下方式组织我的包结构 com.jameselsey.. 控制器-控制器/操作转到此处 服务-事务服务类,由控制器调用 域-应用程序使用的我的域类/对象 D
这更多是出于好奇而不是任何重要问题,但我只是想知道 memmove 中的以下片段文档: Copying takes place as if an intermediate buffer were us
路径压缩涉及将根指定为路径上每个节点的新父节点——这可能会降低根的等级,并可能降低路径上所有节点的等级。有办法解决这个问题吗?有必要处理这个吗?或者,也许可以将等级视为树高的上限而不是确切的高度? 谢
我有两个类,A 和 B。A 是 B 的父类,我有一个函数接收指向 A 类型类的指针,检查它是否也是 B 类型,如果是将调用另一个函数,该函数接受一个指向类型 B 的类的指针。当函数调用另一个函数时,我
有没有办法让 valgrind 使用多个处理器? 我正在使用 valgrind 的 callgrind 进行一些瓶颈分析,并注意到我的应用程序中的资源使用行为与在 valgrind/callgrind
假设我们要使用 ReaderT [(a,b)]超过 Maybe monad,然后我们想在列表中进行查找。 现在,一个简单且不常见的方法是: 第一种可能性 find a = ReaderT (looku
我的代码似乎有问题。我需要说的是: if ( $('html').attr('lang').val() == 'fr-FR' ) { // do this } else { // do
根据this文章(2018 年 4 月)AKS 在可用性集中运行时能够跨故障域智能放置 Pod,但尚不考虑更新域。很快就会使用更新域将 Pod 放入 AKS 中吗? 最佳答案 当您设置集群时,它已经自
course | section | type comart2 : bsit201 : lec comart2 :
我正在开发自己的 SDK,而这又依赖于某些第 3 方 SDK。例如 - OkHttp。 我应该将 OkHttp 添加到我的 build.gradle 中,还是让我的 SDK 用户包含它?在这种情况下,
随着 Rust 越来越充实,我对它的兴趣开始激起。我喜欢它支持代数数据类型,尤其是那些匹配的事实,但是对其他功能习语有什么想法吗? 例如标准库中是否有标准过滤器/映射/归约函数的集合,更重要的是,您能
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 这个问题似乎与 help center 中定义的范围内的编程无关。 . 关闭 9 年前。 Improve
我一直在研究 PHP 中的对象。我见过的所有示例甚至在它们自己的对象上都使用了对象构造函数。 PHP 会强制您这样做吗?如果是,为什么? 例如: firstname = $firstname;
...比关联数组? 关联数组会占用更多内存吗? $arr = array(1, 1, 1); $arr[10] = 1; $arr[] = 1; // <- index is 11; does the
我是一名优秀的程序员,十分优秀!