【问题标题】:Which C++ standard is the default when compiling with g++?使用 g++ 编译时,哪个 C++ 标准是默认的?
【发布时间】:2017-11-27 19:10:33
【问题描述】:

我有一段代码如下所示。假设它在一个名为example.cpp的文件中

#include <fstream>
#include <string> // line added after edit for clarity

int main() {
    std::string filename = "input.txt";
    std::ifstream in(filename);

    return 0;
}

在 Windows 上,如果我输入cmd 命令g++ example.cpp,它将失败。我认为这是一长串错误,主要是由于链接器抱怨无法从 string 转换为 const char*

但如果我使用像这样的附加参数运行编译器:g++ -std=c++17 example.cpp,它将编译并正常工作,没有任何问题。

当我运行前一个命令时会发生什么?我猜 C++ 编译器的默认 version 标准会被调用,但我不知道是哪个?作为程序员/开发人员,我是否应该始终使用带有额外参数的后一个命令?

【问题讨论】:

  • 取决于你的 gcc 版本。
  • 咳咳@Downvoters;这并不像你想象的那么明显,而且这个问题用一个很好的(虽然不可移植的)例子写得很好。
  • 我认为-std 改变了编译器的语义,而不是运行一个完全不同的编译器。您是否对编译器(“gcc” vs “clang” vs ...)或编译器尝试遵循的标准(“C++17” vs “C++11” vs ....)感兴趣?
  • @gmatht 后者绝对是我想知道的。我想我把像“-std=c++11”这样的命令参数误解为执行一个完全独立的编译器。

标签: c++ g++ mingw


【解决方案1】:

如果您的 g++ 版本晚于 4.7,我认为您可以找到支持的 C++ 标准的默认版本,如下所示:

g++ -dM -E -x c++  /dev/null | grep -F __cplusplus

我机器上的一个例子:

mburr@mint17 ~ $ g++ --version | head -1
g++ (Ubuntu 4.8.4-2ubuntu1~14.04.3) 4.8.4
mburr@mint17 ~ $ g++ -dM -E -x c++  /dev/null | grep -F __cplusplus
#define __cplusplus 199711L

一些参考资料:

【讨论】:

【解决方案2】:

你也可以用gdb检查

  1. $ g++ example.cpp -g 编译带有-g 标志的程序以生成调试信息
  2. $ gdb a.out 使用 gdb 调试程序
  3. (gdb) b main在main处下断点
  4. (gdb) run 运行程序(将在断点处暂停)
  5. (gdb) info source

打印出类似的内容:

Current source file is example.cpp
Compilation directory is /home/xxx/cpp
Located in /home/xxx/cpp/example.cpp
Contains 7 lines.
Source language is c++.
Producer is GNU C++14 6.3.0 20170516 -mtune=generic -march=x86-64 -g.
Compiled with DWARF 2 debugging format.
Does not include preprocessor macro info.

有编译器使用的标准:Producer is GNU C++14

如果您使用-std=c++11(例如)重新编译您的程序,gdb 会检测到它: Producer is GNU C++11

【讨论】:

    【解决方案3】:

    我相信可以通过查看手册页来判断(至少对于 g++):

    -std 的描述下,手册页列出了所有 C++ 标准,包括 GNU 方言。在一个特定的标准下,它是相当不显眼的,This is the default for C++ code.(C 标准有类似的声明:This is the default for C code.)。

    例如,对于g++/gcc version 5.4.0,它列在gnu++98/gnu++03 下,而对于g++/gcc version 6.4.0,它列在gnu++14 下。

    【讨论】:

      【解决方案4】:

      g++ 手册页实际上告诉了 C++ 代码的默认标准是什么。

      使用以下脚本显示相关部分:

      man g++ | col -b | grep -B 1 -e '-std.* default'
      

      例如,在 RHEL 6 g++ (GCC) 4.4.7 20120313 (Red Hat 4.4.7-23) 中,输出:

               gnu++98
                 GNU dialect of -std=c++98.  This is the default for C++ code.
      

      在 Fedora 28 g++ (GCC) 8.1.1 20180502 (Red Hat 8.1.1-1) 中,输出:

             gnu++1y
                 GNU dialect of -std=c++14.  This is the default for C++ code.  The name gnu++1y is deprecated.
      

      【讨论】:

        【解决方案5】:

        我猜 C++ 编译器的默认版本会被调用,但我不知道是哪个?

        这只能通过阅读特定编译器版本的文档来猜测。

        如果使用最近 GCC,我建议首先通过运行了解您使用的是什么版本

        g++ -v
        

        g++ --version
        

        然后参考特定版本的 GCC 版本。例如对于 GCC 7,请阅读 GCC 7 changes

        或者,运行

        g++ -dumpspecs
        

        并破译默认的所谓spec file

        顺便说一句,您可以通过编码确保(例如,在一些常见的头文件中)C++ 至少是 C++17

         #if __cplusplus < 201412L
         #error expecting C++17 standard
         #endif
        

        我实际上建议这样做。

        PS。实际上,将 C++98 和 C++17 视为两种不同语言(例如,像 Ocaml4 和 C++11 一样)。要求您的用户拥有支持某些已定义语言标准(例如 C++11)的编译器,而不是某些特定版本的 GCC。另请阅读package managers

        【讨论】:

        • 您引用的GCC 7 changes 的哪一部分提到如果未指定 -std=xxx 选项是默认选项?
        • 每个版本的 GCC 编译器文档都明确规定了 C 和 C++ 的默认语言标准。无需猜测。请参阅下面的答案。
        【解决方案6】:

        在你的命令行输入g++ --version会显示编译器的版本,你可以从中推断出默认的标准。因此,您无法直接判断,但您可以推断,但需要付出一些努力。

        编译器假定#define__cplusplus,可用于提取他们声称在编译时实现的标准;但很多人还没有这样做。

        (并且不要忘记包含您需要的所有 C++ 标准库头文件:例如,std::string 的头文件在哪里?不要依赖您的 C++ 标准库实现,包括自动包含其他头文件 - 这样做你没有编写可移植的 C++。)

        【讨论】:

        • 错误,因为g++ --version 只显示GCC 编译器的版本,而不是默认标准。
        • @Manuel 你不应该依赖它。始终 #include 您在标准库中使用的内容。
        • 是的,但是还有额外的间接性
        • @πάνταῥεῖ 谢谢,已经注意到了。另一方面,输入 g++ --version 只是告诉我 g++ 的版本。它没有说明它使用的是什么默认的“-std=c++”
        • 抱歉,很明显--version 没有返回直接使用的标准。现在已经说明了明显的;-)
        【解决方案7】:

        man g++ | grep "这是 C++ 代码的默认值"

        【讨论】:

          【解决方案8】:

          您的问题是针对 gnu 编译器的,因此最好适当地标记它,而不仅仅是 C++ 和 C++11。

          您的代码将使用与 C++11 及更高版本兼容的任何编译器(和相关库)进行编译。

          原因是 C++11 引入了一个接受 const std::string &amp;std::ifstream 构造函数。在 C++11 之前,无法传递 std::string,因此您的代码中必须传递 filename.c_str() 而不是 filename

          根据来自 gnu 的信息,https://gcc.gnu.org/projects/cxx-status.html#cxx11,gcc.4.8.1 是第一个完全支持 C++11 的版本。在命令行g++ -v 会提示g++ 告诉你它的版本号。

          如果您深入研究文档,您可能能够找到首先支持足够功能的版本/子版本,以便您的代码(如给定)能够编译。但这样的版本将支持某些 C++11 特性,而不支持其他特性。

          由于 windows 不是随 g++ 一起分发的,因此您将拥有某人(您?)选择安装的任何版本。不会有默认版本的 g++ 与您的 windows 版本相关联。

          【讨论】:

          • 这是对的,但与其说是对原始问题的真正回答,不如说是一个冗长而有用的评论。
          【解决方案9】:

          GCC 手册中指定了 C 和 C++ 的默认语言标准。您可以通过以下方式找到这些:

          浏览到https://gcc.gnu.org/onlinedocs/

          选择您感兴趣的 GCC 版本的 GCC #.## Manual 链接,例如对于 GCC 7.5.0:

          https://gcc.gnu.org/onlinedocs/gcc-7.5.0/gcc/

          单击主题链接GCC 支持的语言标准,然后单击主题C++ 语言(或C 语言)。这些主题中的任何一个都会有一个句子,例如:

          如果没有给出 C++ 语言方言选项,则默认值为 -std=gnu++14。

          如果没有给出 C 语言方言选项,则默认值为 -std=gnu11。

          以上两个示例适用于 GCC 7.5.0。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2017-05-29
            • 1970-01-01
            • 2018-04-09
            • 1970-01-01
            • 1970-01-01
            • 2021-07-14
            • 2019-12-16
            • 2015-02-14
            相关资源
            最近更新 更多