Mat*_* M. 113
编辑:
gcc的人真的改善了gcc的诊断经验(比赛啊).他们创建了维基页面来展示它在这里.gcc 4.8现在也具有相当好的诊断功能(gcc 4.9x增加了颜色支持).Clang仍处于领先地位,但差距正在缩小.
原版的:
对于学生,我会无条件地推荐Clang.
gcc和Clang之间生成代码的表现现在还不清楚(虽然我认为gcc 4.7仍然领先,但我还没有看到确凿的基准),但对于学生来说,学习它并不重要.
另一方面,Clang极其清晰的诊断对初学者来说更容易解释.
考虑一下这个简单的片段:
#include <string>
#include <iostream>
struct Student {
std::string surname;
std::string givenname;
}
std::ostream& operator<<(std::ostream& out, Student const& s) {
return out << "{" << s.surname << ", " << s.givenname << "}";
}
int main() {
Student me = { "Doe", "John" };
std::cout << me << "\n";
}
Run Code Online (Sandbox Code Playgroud)
你会立刻注意到在定义Student类之后缺少分号,对吧:)?
好吧,gcc也注意到它,经过时尚:
prog.cpp:9: error: expected initializer before ‘&’ token
prog.cpp: In function ‘int main()’:
prog.cpp:15: error: no match for ‘operator<<’ in ‘std::cout << me’
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/ostream:112: note: candidates are: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(std::basic_ostream<_CharT, _Traits>& (*)(std::basic_ostream<_CharT, _Traits>&)) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/ostream:121: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(std::basic_ios<_CharT, _Traits>& (*)(std::basic_ios<_CharT, _Traits>&)) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/ostream:131: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(std::ios_base& (*)(std::ios_base&)) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/ostream:169: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(long int) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/ostream:173: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(long unsigned int) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/ostream:177: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(bool) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/bits/ostream.tcc:97: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(short int) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/ostream:184: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(short unsigned int) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/bits/ostream.tcc:111: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(int) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/ostream:195: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(unsigned int) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/ostream:204: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(long long int) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/ostream:208: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(long long unsigned int) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/ostream:213: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(double) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/ostream:217: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(float) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/ostream:225: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(long double) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/ostream:229: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(const void*) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/bits/ostream.tcc:125: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(std::basic_streambuf<_CharT, _Traits>*) [with _CharT = char, _Traits = std::char_traits<char>]
Run Code Online (Sandbox Code Playgroud)
而且Clang也不是在这里主演,但仍然:
/tmp/webcompile/_25327_1.cc:9:6: error: redefinition of 'ostream' as different kind of symbol
std::ostream& operator<<(std::ostream& out, Student const& s) {
^
In file included from /tmp/webcompile/_25327_1.cc:1:
In file included from /usr/include/c++/4.3/string:49:
In file included from /usr/include/c++/4.3/bits/localefwd.h:47:
/usr/include/c++/4.3/iosfwd:134:33: note: previous definition is here
typedef basic_ostream<char> ostream; ///< @isiosfwd
^
/tmp/webcompile/_25327_1.cc:9:13: error: expected ';' after top level declarator
std::ostream& operator<<(std::ostream& out, Student const& s) {
^
;
2 errors generated.
Run Code Online (Sandbox Code Playgroud)
我故意选择一个触发不明确错误信息的例子(来自语法中的含糊不清),而不是典型的"哦,我的上帝克朗读我的思想"的例子.尽管如此,我们还是注意到Clang避免了大量的错误.无需吓跑学生.
Man*_*rse 34
截至目前,GCC对C++ 11功能的支持比Clang更好,更完整.此外,GCC的代码生成器执行比Clang更好的优化(根据我的经验,我没有看到任何详尽的测试).
另一方面,Clang经常比GCC更快地编译代码,并在代码出现问题时产生更好的错误消息.
选择哪一个真正取决于对您来说重要的事情.我重视C++ 11支持和代码生成质量,而不是重视编译的便利性.因此,我使用GCC.对你而言,权衡可能会有所不同.
Ray*_*ger 23
我使用它们,因为有时它们会提供不同的,有用的错误消息
当其中一个核心开发人员首次尝试使用clang进行编译时,Python项目能够找到并修复许多小bug.
ide*_*n42 11
我同时使用了Clang和GCC,我发现Clang有一些有用的警告,但是对于我自己的光线跟踪基准 - 它一直比GCC慢5-15%(当然是用盐,但试图使用类似的优化标志对彼此而言).
所以现在我使用Clang静态分析及其对复杂宏的警告:(尽管现在GCC的警告非常好 - gcc4.8 - 4.9).
一些考虑:
***** - 这些领域正在积极开发中,可能很快就会得到支持
对于学生级别的课程,Clang的优势在于,默认情况下更严格.C标准.例如,GCC会在没有警告的情况下接受以下K&R版本的Hello World,但Clang拒绝了一些非常具有描述性的错误消息:
main()
{
puts("Hello, world!");
}
Run Code Online (Sandbox Code Playgroud)
有了GCC,你必须-Werror让它真正指出这不是一个有效的C89程序.此外,您仍然需要使用c99或gcc -std=c99获取C99语言.