当我愚蠢地假设如果Visual Studio准备转到我右键单击的变量的定义时,我忍受了一个令人沮丧的几个小时试图解开某个编译器错误,然后该变量必须是定义。这就是我习惯的行为。
涉及winsvc.h
的案例涉及SERVICE_STATUS
。如果我成功编译了我的项目,并右键单击SERVICE_STATUS
到"转到定义",那么它自然会带我到winsvc.h
中的相关行。
但是,当我注释掉我的#include <winsvc.h>
以便我无法成功编译时,我仍然可以右键单击我的文件中的SERVICE_STATUS
,因为它不再被定义...仍然被带到winsvc.h
。
如果我尝试用某些其他文件(特别是由我编写的文件)执行此操作 - 注释掉定义某些变量的文件也会破坏&#34;转到定义&#34;功能。这对我来说很有意义 - 如果没有定义,那就不要去了。
那么winsvc.h
有什么特别之处?特别是其他文件(bug?feature?)现象适用于什么?虽然这个问题已经asked before,但没有一个答案被接受,而且就我所关注的问题而言,所有答案似乎都误解了这个问题。
答案 0 :(得分:3)
首先,并且更强烈地重申@MatteoItalia的评论,IntelliSense 不是代码分析器或验证器。相反,它是一个即时的&#34;参考调度员&#34;使用 not 的快速启发式算法进行编译器级解析。这是设计 - 引用MSVC ++团队的Tag Parsing C++的Thierry Miceli(我的亮点是粗体):
标记解析器在Visual Studio 2010中用于填充取代NCB文件的SQL数据库。 VC ++的所有浏览功能都以某种方式依赖于标记解析器提供的结果。这些包括类视图,调用层次结构,转到定义/声明,获取所有引用,快速搜索,导航栏和VCCodeModel。
[...]它是一个模糊的解析器,这意味着它不是试图严格识别和验证完整的C ++语法(我们有一个很好的编译器前端来做到这一点),它懒洋洋地匹配一个输入的令牌流有一些模式。
[...]标记解析器不会尝试理解源代码中的每个符号或标识符。 [...] 如果声明的类型规范中的名称无法通过我们的C ++编译器解析,则这不会阻止标记解析器识别声明,它将显示在类视图中
另一点是SDF数据库是每个项目,而不是每个文件。一旦项目#include&#39; d(和used)&lt; winsvc.h&gt;中的文件,IntelliSense就会识别同一项目中任何其他文件中的SERVICE_STATUS。这很容易验证 - 只需在项目中添加一个新的空.cpp文件,然后键入SERVICE_STATUS。 &#34; 转到定义&#34;将转到&lt; winsvc.h&gt;定义,即使标题未包含在新文件中,即使文件本身根本不可编译。
最后,如果项目只包含一个文件,该文件在删除#include
后不再编译,则SDF可能不重建,并记住现在陈旧的引用。