Подтвердить что ты не робот

Почему стандартная библиотека С++ уже не включена в любой источник С++?

В С++ стандартная библиотека обернута в пространство имен std, и программист не должен определять что-либо внутри этого пространства имен. Разумеется, стандарт включает файлы, которые не накладывают друг на друга имена внутри стандартной библиотеки (поэтому никогда не стоит включать стандартный заголовок).

Тогда почему не вся стандартная библиотека включена по умолчанию, а не заставляет программистов писать, например, #include <vector> каждый раз? Это ускорит компиляцию и, поскольку компиляторы могут начать с предварительно построенной таблицы символов для всех стандартных заголовков.

Предварительно включив все проблемы, можно решить некоторые проблемы с переносимостью: например, если вы включили <map>, то определили, какие символы приняты в пространстве имен std, но не гарантируют, что другие стандартные символы не загруженный в него, и, например, вы могли бы (теоретически) оказаться в std::vector также доступным.

Иногда бывает, что программист забывает включать стандартный заголовок, но программа компилируется в любом случае из-за зависимости конкретной реализации. При перемещении программы в другую среду (или просто другую версию того же самого компилятора) один и тот же исходный код может, однако, прекратить компиляцию.

С технической точки зрения я могу представить компилятору только предварительную загрузку (с помощью mmap) оптимальной таблицы символов идеального хэша для стандартной библиотеки. Это нужно делать быстрее, чем загружать и выполнять синтаксический анализ С++ даже одного стандартного файла include и иметь возможность быстрее искать имена std::. Эти данные также будут доступны только для чтения (таким образом, вероятно, позволяя более компактное представление, а также разделяемое между несколькими экземплярами компилятора).

Тем не менее, они просто должны, поскольку я никогда не реализовал это.

Единственный недостаток, который я вижу, заключается в том, что мы программисты на C++ теряем компиляцию кофе-брейков и посещений: -)

ИЗМЕНИТЬ

Просто чтобы прояснить преимущество main, которое я вижу, для программистов, которые сегодня, несмотря на то, что стандартная библиотека С++ является единственным монолитным пространством имен, должны знать, какая часть (включая файл) содержит функция/класса. Чтобы добавить оскорбление к травме, когда они совершают ошибку, и забыть файл включения, код может компилироваться или нет в зависимости от реализации (что приводит к непереносимым программам).

4b9b3361

Ответ 1

Короткий ответ - это потому, что предполагается, что язык С++ не используется

Есть веские причины для этого:

  • загрязнение пространства имен - даже если это можно было бы смягчить, поскольку пространство имен std должно быть самосогласованным, а программист не вынужден использовать using namespace std;. Но включая всю библиотеку с using namespace std;, безусловно, приведет к большому беспорядку...
  • заставить программиста объявить модули, которые он хочет использовать, чтобы случайно не вызвать неправильную стандартную функцию, поскольку стандартная библиотека теперь огромна, и не все программисты знают все модули
  • история: у С++ все еще есть сильное наследование от C, где пространство имен не существует и где стандартная библиотека должна использоваться как любая другая библиотека.

Чтобы идти в вашем понимании, Windows API - это пример, в котором у вас есть только один большой include (windows.h), который загружает многие другие более мелкие файлы include. И на самом деле, предварительно скомпилированные заголовки позволяют достаточно быстро

Итак, IMHO новый язык, основанный на С++, может решить автоматически объявить всю стандартную библиотеку. Новый основной релиз также может это сделать, но он может интенсивно разрывать код, используя директиву using namespace и иметь пользовательские реализации с использованием тех же имен, что и некоторые стандартные модули.

Но все общие языки, которые я знаю (С#, Python, Java, Ruby), требуют от программиста объявления частей стандартной библиотеки, которые он хочет использовать, поэтому я полагаю, что систематическое предоставление каждой части стандартной библиотеки еще более неудобный, чем действительно полезный для программиста, по крайней мере, пока кто-то не найдет, как объявить части, которые не должны быть загружены - вот почему я говорил о новой производной от С++

Ответ 2

Большинство стандартных библиотек С++ основаны на шаблонах, что означает, что код, который они будут генерировать, в конечном счете будет зависеть от того, как вы их используете. Другими словами, очень мало того, что можно было скомпилировать, прежде чем создавать шаблон, например std::vector<MyType> m_collection;.

Кроме того, С++, вероятно, является самым медленным языком для компиляции, и существует большая работа по разбору, которую компиляторы должны делать, когда вы #include заголовочный файл, который также включает в себя другие заголовки.

Ответ 3

Ну, во-первых, С++ пытается придерживаться "вы платите только за то, что используете".
Стандартная библиотека иногда не является частью того, что вы используете вообще, или даже того, что вы могли бы использовать, если хотите.
Кроме того, вы можете заменить его, если есть причина для этого: см. libstdc++ и libc++.
Это означает, что просто включение всего этого без вопросов не является на самом деле такой яркой идеей.

В любом случае, комитет медленно подключается к созданию модульной системы (требуется много времени, надеюсь, он будет работать для С++ 1z: С++ Modules - почему они были удалены из С++ 0x? Вернутся ли они позже?), и когда это сделает большинство недостатков, чтобы включить больше стандартной библиотеки, чем строго необходимо, должно исчезнуть, а отдельные модули должны более чисто исключать символы, которые они не нужно содержать.
Кроме того, поскольку эти модули предварительно анализируются, они должны обеспечить улучшение скорости компиляции.

Ответ 4

Вы предлагаете два преимущества вашей схемы:

  • Время компиляции. Но ничто в стандарте не позволяет реализации делать то, что вы предлагаете [*], с очень небольшой модификацией: что предварительно скомпилированная таблица отображается только тогда, когда единица перевода включает в себя по крайней мере один стандартный заголовок. Из POV стандарта нет необходимости налагать потенциальную нагрузку на реализацию по проблеме QoI.

  • Удобство для программистов: по вашей схеме нам не нужно будет указывать, какие заголовки нам нужны. Мы делаем это для поддержки реализаций С++, которые решили не реализовывать вашу идею создания стандартных заголовков монолитных (в настоящее время их всех), и поэтому из POV стандарта С++ это вопрос "поддержки существующей практики и свобода реализации при стоимости, которую программисты считают приемлемой". Какой вид лозунга С++, не так ли?

Так как никакая реализация С++ (что я знаю) на самом деле не делает этого, мое подозрение в том, что на самом деле это не дает улучшения производительности, которое, по вашему мнению, оно делает. Microsoft предоставляет предварительно скомпилированные заголовки (через stdafx.h) именно для этой причины производительности, и все же она по-прежнему не дает вам возможности для "всех стандартных библиотек", вместо этого она требует от вас сказать, чего вы хотите. легко для этой или любой другой реализации предоставить заголовок, специфичный для реализации, который имеет тот же эффект, что и все стандартные заголовки. Это говорит мне, что, по крайней мере, по мнению Microsoft, не было бы большой общей пользы для этого.

Если бы реализациями стали предлагать монолитные стандартные библиотеки с очевидным повышением производительности во время компиляции, тогда мы обсудили, будет ли хорошая идея для стандарта С++ продолжать разрешать реализации, которые этого не делают. Как бы то ни было, это должно быть.

[*] За исключением, возможно, того факта, что <cassert> определяется как отличающееся поведение в соответствии с определением NDEBUG в том месте, в которое оно было включено. Но я думаю, что реализация могла бы просто предварительно обработать пользовательский код как обычно, а затем отобразить в одной из двух разных таблиц в зависимости от того, была ли она определена.

Ответ 5

Я думаю, что ответ сводится к философии С++ о том, что вы не платите за то, что вы не используете. Это также дает вам большую гибкость: вы не вынуждены использовать части стандартной библиотеки, если они вам не нужны. И тогда возникает тот факт, что некоторые платформы могут не поддерживать такие вещи, как выброс исключений или динамическое выделение памяти (например, процессоры, используемые в Arduino, например). И еще одна вещь, о которой вы сказали, неверна. Пока это не шаблонный шаблон, вам разрешено добавлять операторы swap в пространство имен std для ваших собственных классов.

Ответ 6

Прежде всего, я боюсь, что прелюдия немного запоздала для игры. Вернее, видеть, что прелюдии нелегко расширяемы, мы должны довольствоваться очень тонким (встроенные типы...).

В качестве примера скажем, что у меня есть программа С++ 03:

#include <boost/unordered_map.hpp>

using namespace std;
using boost::unordered_map;

static unordered_map<int, string> const Symbols = ...;

Все работает отлично, но внезапно, когда я перехожу на С++ 11:

error: ambiguous symbol "unordered_map", do you mean:
- std::unordered_map
- boost::unordered_map

Поздравляем, вы придумали наименее отсталую совместимую схему для выращивания стандартной библиотеки (просто шутите, кто-то, кто использует using namespace std;, виноват...).


Хорошо, пусть не предварительно их включить, но все равно связывает идеальную хеш-таблицу. Усиление производительности будет стоить того, правильно?

Хорошо, я серьезно сомневаюсь. Прежде всего потому, что стандартная библиотека крошечная по сравнению с большинством других заголовочных файлов, которые вы включили (подсказка: сравните ее с Boost). Поэтому прирост производительности будет... небольшим.

О, не все программы большие; но мелкие быстро компилируются (в силу малого), а большие - гораздо больше кода, чем заголовки стандартной библиотеки, поэтому вы не получите много пробега.

Примечание. И да, я проверил поиск файла в проекте с помощью "только" сотен директив -I; вывод заключался в том, что предварительная вычисление "включить путь" к карте "местоположение файла" и подача ее на gcc привела к 30% -ному ускорению (после использования ccache уже). Создание его и поддержание его в актуальном состоянии было сложным, поэтому мы никогда не использовали его...


Но можем ли мы хотя бы включить условие, которое компилятор мог бы сделать в стандарте?

Насколько я знаю, он уже включен. Я не могу вспомнить, есть ли конкретная реклама об этом, но стандартная библиотека действительно является частью "реализации", поэтому разрешение #include <vector> на внутреннюю хэш-карту в любом случае будет подпадать под правило as-if.


Но они все равно могли это сделать!

И потеряйте любую гибкость. Например, Clang может использовать libstdС++ или libС++ в Linux, и я считаю, что он совместим с производным Dirkumware, который поставляется с VС++ (или, если не полностью, по крайней мере, сильно).

Это еще одна точка настройки: если стандартная библиотека не соответствует вашим потребностям или вашим платформам, поскольку она в основном обрабатывается, как любая другая библиотека, вы можете с легкостью заменить часть большей части ее.


Но! Но!

#include <stdafx.h>

Если вы работаете в Windows, вы это узнаете. Это называется предварительно скомпилированным заголовком. Он должен быть включен первым (или все преимущества потеряны), а вместо обмена файлами вы берете эффективное двоичное представление этих проанализированных файлов (например, сериализованная версия AST, возможно, с уже выполненным разрешением по типу), который сбрасывается от 30% до 50% работы. Да, это близко к вашему предложению; это компьютерная наука для вас, всегда есть кто-то другой, кто сначала думал об этом...

Clang и gcc имеют аналогичный механизм; хотя из того, что я слышал, может быть так больно использовать, что люди предпочитают более прозрачный кэш на практике.


И все это сойдет на нет с модулями.

Это истинное решение этой безупречности для предварительной обработки/синтаксического анализа/определения типа. Поскольку модули действительно изолированы (т.е. В отличие от заголовков, не подлежащих заказу включения), эффективное двоичное представление (например, предварительно скомпилированные заголовки) может быть предварительно вычислено для каждого модуля, от которого вы зависите.

Это означает не только стандартную библиотеку, но и все библиотеки.

Ваше решение, более гибкое и одетное в девятки!

Ответ 7

Можно использовать альтернативную реализацию стандартной библиотеки С++ для той, которая поставляется вместе с компилятором. Или оберните заголовки одним определением, чтобы добавить, включить или отключить функции (см. Заголовки GNU-обертки). Обычные текстовые заголовки и модель включения C являются более мощным и гибким механизмом, чем двоичный черный ящик.