Какой стандарт С++ является стандартным при компиляции с 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
, он будет компилироваться и работать нормально, без проблем.
Что происходит, когда я запускаю прежнюю команду? Я предполагаю, что стандартная версия version компилятора С++ вызывается, но я не знаю, что? И как программист/разработчик, должен ли я всегда использовать последнюю команду с дополнительным аргументом?
Ответы
Ответ 1
Если ваша версия g++
более поздняя, чем 4.7, я думаю, вы можете найти стандартную версию стандарта С++, поддерживаемую следующим образом:
g++ -dM -E -x c++ /dev/null | grep -F __cplusplus
Пример из моей машины:
[email protected] ~ $ g++ --version | head -1
g++ (Ubuntu 4.8.4-2ubuntu1~14.04.3) 4.8.4
[email protected] ~ $ g++ -dM -E -x c++ /dev/null | grep -F __cplusplus
#define __cplusplus 199711L
Некоторые ссылки:
Ответ 2
Я предполагаю, что по умолчанию используется компилятор С++, но я не знаю, что?
Это возможно только при чтении документации вашей конкретной версии компилятора.
Если вы используете недавний GCC, я сначала хочу понять, какую версию вы используете, запустив
g++ -v
или
g++ --version
а затем обратитесь к версии конкретного выпуска GCC. Например, для GCC 7, прочитайте GCC 7 изменится и т.д.
Кроме того, запустите
g++ -dumpspecs
и расшифруйте по умолчанию так называемый spec файл.
Кстати, вы могли бы обеспечить (например, в каком-то из вашего общего файла заголовка), что С++ по крайней мере С++ 17 путем кодирования
#if __cplusplus < 201412L
#error expecting C++17 standard
#endif
и я действительно рекомендую сделать это таким образом.
PS. Собственно, подумайте, что С++ 98 и С++ 17 являются двумя разными языками (например, Ocaml4 и С++ 11). Требовать, чтобы ваш пользователь имел компилятор, поддерживающий некоторый определенный языковой стандарт (например, С++ 11), а не определенную версию GCC. Читайте также о менеджерах пакетов.
Ответ 3
Ввод g++ --version
в командной оболочке покажет версию компилятора, и из этого вы можете сделать вывод о стандарте по умолчанию. Поэтому вы не можете сказать напрямую, но вы можете сделать это с некоторыми усилиями.
Составители должны #define
__cplusplus
, которые могут быть использованы для извлечения стандарта, который они хотят реализовать во время компиляции; но многие еще этого не делают.
(И не забудьте указать все стандартные заголовки библиотеки С++, которые вам нужны: где, например, один для std::string
? Не полагайтесь на свою стандартную библиотечную реализацию С++, включая другие заголовки, автоматически, делая это не пишут портативный С++.)
Ответ 4
Я считаю, что можно посмотреть, посмотрев страницу руководства (по крайней мере, для g++):
В описании -std
на странице руководства перечислены все стандарты С++, включая диалоги 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
.
Ответ 5
Ваш вопрос специфичен для компиляторов gnu, поэтому, вероятно, лучше пометить его соответствующим образом, а не только С++ и С++ 11.
Ваш код будет компилироваться с любыми компиляторами (и соответствующими библиотеками), совместимыми с С++ 11 и более поздними версиями.
Причина в том, что С++ 11 представил конструктор std::ifstream
, который принимает const std::string &
. До того, как С++ 11, a std::string
не удалось передать, и в вашем коде было бы необходимо пройти filename.c_str()
, а не filename
.
Согласно информации из gnu, https://gcc.gnu.org/projects/cxx-status.html#cxx11, gcc.4.8.1 была первой версией, полностью поддерживающей С++ 11. В командной строке g++ -v
будет prod g++
сообщать вам номер своей версии.
Если вы вникнете в документацию, вы сможете найти версию /subversion, в которой вначале поддерживались достаточные возможности, поэтому ваш код - как указано - будет компилироваться. Но такая версия поддерживает некоторые функции С++ 11, а не другие.
Так как окна не распределены с g++, у вас будет какая-то версия, которую кто-то (вы?) выбрали для установки. Не будет версии по умолчанию g++, связанной с вашей версией окон.
Ответ 6
Вы также можете проверить с помощью 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