Почему не определено main `main (std :: vectorарг) `? - PullRequest
14 голосов
/ 13 августа 2010

Этот вопрос только наполовину насмешливый.Я иногда мечтаю о мире без обнаженных массивов или c-струн.

Если вы используете c ++, не должно ли предпочтительное определение main быть примерно таким:

int main(std::vector<std::string> args)

?

Уже существует несколько определений mainна выбор, почему нет версии в духе C ++?

Ответы [ 9 ]

11 голосов
/ 13 августа 2010

Поскольку C ++ был разработан для (почти) обратной совместимости с кодом C.

Бывают случаи, когда код C ломается в компиляторе C ++, но они довольно редки, и, как правило, есть веская причина, почему требуется такая поломка.

Но изменение сигнатуры main, хотя и удобно для нас, не обязательно . Для кого-то, портирующего код из C, это будет просто другая вещь, которую вам придется изменить, без особой выгоды.

Другая причина в том, что std::vector - это библиотека, а не часть основного языка. И так, вам нужно было бы #include <vector> в каждой C ++ программе.

И, конечно, в ранние годы C ++ не имел вектора . Поэтому, когда вектор был добавлен к языку, он, конечно, мог бы изменить сигнатуру main, но тогда они нарушали бы не только код на C, но и все существующие программы на C ++.

Стоит ли это того?

10 голосов
/ 13 августа 2010

Есть и другая причина, кроме совместимости с C. В C ++, стандартная библиотека должна быть полностью необязательной . В самом языке C ++ нет ничего, что заставляло бы вас использовать такие вещи из стандартной библиотеки, как std::string и std::vector, и это полностью задумано. На самом деле, именно так вы должны иметь возможность использовать некоторые части стандартной библиотеки без необходимости использовать другие (хотя это привело к некоторым обычно раздражающим вещам, таким как std::ifstream и std::ofstream, работающим на const char* C- строки стиля, а не на std::string объектах).

Теория заключается в том, что вы должны быть в состоянии взять язык C ++ и использовать любую библиотеку объектов, контейнеров и т. Д., Какую захотите, будь то стандартная библиотека или какая-то проприетарная библиотека (например, Qt, MFC) или что-то, что вы создали сами. Определение main для принятия аргумента, состоящего из типов, определенных в стандартной библиотеке, отрицательно сказывается на этой цели разработки.

5 голосов
/ 13 августа 2010

Потому что это заставит вас включить <vector> и <string>.

4 голосов
/ 14 августа 2010

Меня постоянно беспокоит то, что как только вы разрешаете сложные типы, вы рискуете выбросить исключения в конструктор типа.И, поскольку язык в настоящее время разработан, нет абсолютно никакого способа поймать такое исключение.Если было решено, что такие исключения должны быть обнаружены, то это потребовало бы значительно больше работы, как для авторов комитетов, так и для авторов компиляторов, что сделало бы это несколько более проблематичным, чем просто сказать «allow std::vector<std::string>>».

Могут быть и другие проблемы.Мне кажется, что «несовместимо со средой выполнения» кажется чем-то вроде красной селедки, учитывая то, что теперь вы можете предоставлять в основном ту же функциональность с помощью макросов.Но что-то вроде этого более сложное.

4 голосов
/ 13 августа 2010

Как и @jalf, я иногда пишу

int main(int argc, char** argv) {
    std::vector<std::string> args(argv, argv+argc);

Но да, как все говорили, main должен быть C-совместимым.Я рассматриваю это как интерфейс к среде выполнения ОС, которая (по крайней мере, в системах, которые я использую) написана на C.

Хотя некоторые среды разработки допускают замены, такие как wmain или _tmain.Вы можете написать свой собственный компилятор / IDE, который будет стимулировать использование int vmain(const std::vector<std::string>& args).

3 голосов
/ 13 августа 2010

Поскольку C ++ существовал задолго до появления стандарта C ++ и в значительной степени основывался на C. И, как и в первоначальном стандарте ANSI C, важной частью его была кодификация существующей практики.

Нет смысла менять что-то, что работает, особенно если это сломает весь существующий код.

Даже ISO C, который прошел немало итераций, все еще серьезно относится к обратной совместимости очень .

2 голосов
/ 13 августа 2010

Множественные определения main () на самом деле не являются множественными определениями.Их три:

  • int main(void) (C99)
  • int main(int argc, char *argv[]) (C99)
  • int main(int argc, char *argv[], char *envp[]) (POSIX, я думаю)

Но в POSIX вы только действительно получаете третий.Тот факт, что вы можете вызывать функцию с дополнительными аргументами, зависит от соглашения о вызовах C.

Вы не можете иметь extern "C" int main(std::vector<std::string> argv), если макет памяти не магически совместим впортативный способ.Среда выполнения вызовет main () с неверными аргументами и завершится ошибкой.Нет простого способа обойти это.

Вместо этого, при условии, что main () не был extern "C", среда выполнения могла пробовать различные поддерживаемые символы по порядку, пока не нашла их.Я предполагаю, что main () по умолчанию extern "C", и что вы не можете перегрузить extern "C" функций.

Для большего удовольствия, void main (void) .

2 голосов
/ 13 августа 2010

По сути, чтобы оставаться совместимым с C. Если мы откажемся от этого, main () будет перемещен в класс.

1 голос
/ 13 августа 2010

Я постараюсь объяснить в лучшем из возможных предложений.

C ++ был разработан для обратной совместимости с C, а std::vector был включен в библиотеку, которая была включена только в C ++.

Кроме того, программы на C ++ и C были разработаны для запуска в оболочках или в командных строках (windows, linux, mac), а ОС передавала аргументы программе в виде массива String.Как ОС действительно может переводить векторы?

Это самая большая причина, о которой я могу подумать, не стесняйтесь критиковать ее.

...