为什么 C++ 错误消息不描述代码中的实际问题?

Why don't C++ error messages describe the actual problem in the code?

为什么 Visual Studio 错误日志显示由某些错误引起的事情,而不是错误本身?我经常发现错误信息毫无用处和意义。

当我犯错时,例如循环依赖,它会抛出一堆错误,例如
syntax error: missing ';' 而不是像 circular dependency detected.

这样的东西

当我忘记包含一些 header 并在我的代码中使用它时,例如 std::map,它只会显示 'map' is not a member of 'std'

它从不告诉您真正的错误,它只显示症状。我知道有时候仅凭这一点你就可以清楚地看出哪里出了问题,但我不想花时间去弄清楚哪里出了问题。我只想尽快修复它。

为什么不能像 Python 和 Pycharm IDE 那样实际显示实际错误?

尽管这个问题可能被认为是题外话,但我会尝试给出一个答案,以阐明为什么有人会认为表达的意见(无用且毫无意义)是“不公平的”。

首先,这不是 Visual studio 的事情。如果您使用过其他 C++ 编译器(gcc/clang/intel 编译器),您会发现错误非常相似。尽管它们看起来“毫无用处”,但一点点经验大有帮助。不仅错误精确、准确和可重现,而且它们遵循标准规范并遵守语言的正式描述。

其次,在将 C++ 与 Python 进行比较时,我们必须画一条线。 C++ 是一种编译语言,这意味着在创建可执行文件之前,必须根据语言规则编写全部代码。这意味着 运行time 分支即使没有执行也会被检查。另一方面,Python 是一种解释性语言。这意味着它会即时验证代码(在执行上下文中具有更丰富的信息),因此以下代码可能 运行 没问题:

def main():
    a = []
    a.append(1)
    print(a)
    # return 9'999 out of 10'000 times
    a.shoot_foot(2) # list object has no attribute 'shoot_foot'
 
if __name__ == '__main__':
    main()

代价是错误(甚至不称其为错误,因为它违反了语言规则)可能会在生产中隐藏和显现。

第三C++是一种强类型语言。这意味着类型是静态检查的,代价是要求 you 对它们是正确的。与 动态类型 Python 不同,对象的类型不能在 运行 时修改,这意味着以编程时“小心”为代价提高了类型安全性。这是 JS 与 TS 之争,人们习惯了不同的风格;对我来说,缺乏类型安全是我在使用 Python 时最怀念的事情。这种能力是以进行类型检查时一些最复杂的错误消息为代价的。

最后,C++ 正在积极改进错误消息,使其信息更丰富、更短。这不是一项容易的任务,但是像 concepts 这样的特性允许程序员明确他们对类型系统施加的限制。此外,静态断言等防御性编程技术可以引入“失败开关”,提前停止编译,从而减少错误并仅保留有关攻击性代码的信息。