Какой стандарт C++ используется по умолчанию при компиляции с g++?
У меня есть кусок кода, который выглядит следующим образом. Допустим, это в файле с именем 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;
}
На окнах, если я наберу в cmd
команда g++ example.cpp
, это не удастся. Это длинный список ошибок, я думаю, в основном из-за того, что компоновщик жалуется на невозможность конвертировать из string
в const char*
,
Но если я запускаю компилятор, используя дополнительный аргумент, например, так: g++ -std=c++17 example.cpp
, он будет компилироваться и нормально работать без проблем.
Что происходит, когда я запускаю прежнюю команду? Я предполагаю, что вызывается стандартный стандарт версии компилятора C++, но я не знаю, какой? И как программист / разработчик, я должен всегда использовать последнюю команду с дополнительным аргументом?
10 ответов
Если ваша версия 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
Некоторые ссылки:
Страница man 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.
Вы также можете проверить с помощью GDB
$ g++ example.cpp -g
Компиляция программы с флагом -g для генерации отладочной информации$ gdb a.out
Отладка программы с помощью gdb(gdb) b main
Поставьте точку останова на главном(gdb) run
Запустить программу (остановится в точке останова)(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
Я считаю, что это можно сказать, посмотрев на страницу руководства (по крайней мере, для g++):
Под описанием -std
На странице man перечислены все стандарты 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
,
Я предполагаю, что вызывается версия компилятора C++ по умолчанию, но я не знаю, какая?
Это возможно только при чтении документации вашей конкретной версии компилятора.
Если вы используете последнюю версию GCC, я рекомендую сначала понять, какую версию вы используете, запустив
g++ -v
или же
g++ --version
а затем обратитесь к версии конкретного выпуска GCC. Например, для GCC 7, прочитайте изменения GCC 7 и т. Д.
Или запустить
g++ -dumpspecs
и расшифровать так называемый spec-файл по умолчанию.
Кстати, вы могли бы гарантировать (например, в некоторых из ваших общих заголовочных файлов), что C++ по крайней мере C++17 путем кодирования
#if __cplusplus < 201412L
#error expecting C++17 standard
#endif
и я действительно рекомендую делать это таким образом.
PS. На самом деле, представьте, что C++98 и C++17 - это два разных языка (например, такие как Ocaml4 и C++11). Требуйте, чтобы ваш пользователь имел компилятор, поддерживающий некоторый определенный языковой стандарт (например, C++11), а не какую-то конкретную версию GCC. Читайте также о менеджерах пакетов.
Typing g++ --version
в вашей командной оболочке будет показана версия компилятора, и из этого вы сможете вывести стандарт по умолчанию. Таким образом, вы не можете сказать прямо, но можете сделать вывод, приложив некоторые усилия.
Компиляторы должны #define
__cplusplus
который может быть использован для извлечения стандарта, который они предполагают реализовать во время компиляции; но многие еще этого не делают.
(И не забудьте включить все заголовки стандартной библиотеки C++, которые вам нужны: где std::string
например? Не полагайтесь на реализацию стандартной библиотеки C++, включая другие заголовки, автоматически - при этом вы не пишете переносимый C++.)
Ваш вопрос относится к компиляторам gnu, поэтому, вероятно, лучше пометить его соответствующим образом, а не просто C++ и C++11.
Ваш код будет компилироваться с любыми компиляторами (и связанными библиотеками), совместимыми с C++11 и более поздними версиями.
Причина в том, что C++11 ввел std::ifstream
конструктор, который принимает const std::string &
, До C++11 std::string
не может быть передано, и это необходимо в вашем коде для передачи filename.c_str()
скорее, чем filename
,
Согласно информации от gnu, https://gcc.gnu.org/projects/cxx-status.html, gcc.4.8.1 была первой версией, полностью поддерживающей C++11. В командной строке g++ -v
будет подталкивать g++
чтобы сообщить вам свой номер версии.
Если вы покопаетесь в документации, вы сможете найти версию / subversion, которая сначала поддерживала достаточно функций, чтобы ваш код - как указано - компилировался. Но такая версия будет поддерживать некоторые функции C++11, а не другие.
Поскольку Windows не распространяется с g ++, у вас будет любая версия, которую кто-то (вы?) Выбрал для установки. Там не будет версии G ++ по умолчанию, связанной с вашей версией Windows.
Стандарты языков по умолчанию для C и C++ указаны в руководствах GCC. Вы можете найти их следующим образом:
Перейдите на https://gcc.gnu.org/onlinedocs/
Выберите ссылку GCC #.## Manual для интересующей вас версии GCC, например, для 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.
Что произойдет, когда я запущу прежнюю команду? Я предполагаю, что вызывается стандарт версии компилятора C++ по умолчанию, но я не знаю, какой именно?
Когда ты бежишь
Стандарт языка C++ по умолчанию, используемый GCC, зависит от используемой вами версии GCC. См. документацию о статусе поддержки языка C++ GCC , которая на момент написания статьи гласит:
Функции C++17 доступны начиная с GCC 5. Этот режим используется по умолчанию в GCC 11; его можно явно выбрать с помощью флага командной строки -std=c++17 или -std=gnu++17, чтобы также включить расширения GNU.
GCC полностью поддерживает стандарт C++ 2014 года. Этот режим используется по умолчанию в GCC 6.1 вплоть до GCC 10 (включительно); его можно явно выбрать с помощью флага командной строки -std=c++14 или -std=gnu++14, чтобы также включить расширения GNU.
GCC полностью поддерживает стандарт C++ 1998 года, измененный техническим исправлением 2003 года и некоторыми более поздними отчетами о дефектах, за исключением функции экспорта, которая позже была удалена из языка. Этот режим используется по умолчанию в версиях GCC до 6.1; его можно явно выбрать с помощью флага командной строки -std=c++98 или -std=gnu++98, чтобы также включить расширения GNU.
Если вас интересует поддержка языка/стандартной библиотеки для других компиляторов, вы можете просмотреть документацию по поддержке Clang C++ или страницу поддержки компилятора cppreference.com .
И как программист/разработчик, должен ли я всегда использовать последнюю команду с дополнительным аргументом?
Я не знаю, стоит ли вам это делать, но очевидно, что вам придется это сделать, если вы хотите/нужно использовать определенный языковой стандарт, если только тот, который вы хотите/нужно использовать, не является стандартом по умолчанию для версии GCC, который вы используете.