Если Ваш код имеет add(0)
и remove(0)
, используйте LinkedList
, и это более симпатично addFirst()
и removeFirst()
методы. Иначе используйте ArrayList
.
И конечно, Гуава ImmutableList является Вашим лучшим другом.
Включая iostream
в исходный файл, компилятор должен сгенерировать код для установки и разрушения стандартной библиотеки ввода-вывода C ++. Вы можете увидеть это, посмотрев на вывод из nm
, который показывает символы (обычно функции) в вашем объектном файле:
$ nm --demangle test_with_iostream
08049914 d _DYNAMIC
08049a00 d _GLOBAL_OFFSET_TABLE_
08048718 t global constructors keyed to main
0804883c R _IO_stdin_used
w _Jv_RegisterClasses
080486d8 t __static_initialization_and_destruction_0(int, int)
08048748 W MyClass::MyClass()
U std::string::size() const@@GLIBCXX_3.4
U std::string::operator[](unsigned int) const@@GLIBCXX_3.4
U std::ios_base::Init::Init()@@GLIBCXX_3.4
U std::ios_base::Init::~Init()@@GLIBCXX_3.4
080485cc t std::__verify_grouping(char const*, unsigned int, std::string const&)
0804874e W unsigned int const& std::min<unsigned int>(unsigned int const&, unsigned int const&)
08049a3c b std::__ioinit
08049904 d __CTOR_END__
... (remaining output snipped) ...
( - demangle
принимает имена функций C ++ » искажено компилятором и дает более значимые имена. Первый столбец - это адрес, если функция включена в исполняемый файл. Второй столбец - это тип. «t» - это код в сегменте «текст». «U» являются символами, связанными из других мест; в данном случае из общей библиотеки C ++.)
Сравните это с функциями, сгенерированными из вашего исходного файла без включения iostream
:
$ nm --demangle test_without_iostream
08049508 d _DYNAMIC
080495f4 d _GLOBAL_OFFSET_TABLE_
080484ec R _IO_stdin_used
w _Jv_RegisterClasses
0804841c W MyClass::MyClass()
080494f8 d __CTOR_END__
... (remaining output snipped) ...
Когда исходный файл включал iostream
, компилятор сгенерировал несколько функций, отсутствующих без iostream
.
Когда исходный файл включает только stdio.h
, сгенерированный двоичный файл аналогичен тесту без iostream
, поскольку стандартная библиотека ввода-вывода C не требует дополнительной инициализации сверх того, что уже происходит в динамической библиотеке C. Вы можете увидеть это, посмотрев на выходные данные нм
, которые идентичны.
В общем, однако, пытаясь интуитивно понять информацию о количестве кода, сгенерированного конкретным исходным файлом, на основе размера файла исполняемый файл не будет иметь смысла; слишком многое может измениться,
Заголовочные файлы обычно представляют собой просто объявления и не приводят непосредственно к созданию машинного кода. Компоновщик достаточно умен, чтобы не извлекать неиспользуемые функции из CRT, поэтому простое включение stdio.h без использования какой-либо из его функций не приведет к увеличению кода в вашем исполняемом файле.
РЕДАКТИРОВАТЬ: Они могут включать встроенные функции, классы, и т.д., которые включают код, но они не должны приводить к увеличению размера вашего исполняемого файла, пока они не будут фактически использованы.
В iostream есть некоторые статические инициализации, а в stdio.h есть только функции и их определения. Поэтому включение iostream приведет к созданию исполняемого файла большего размера.
iostream включает код. stdio.h - нет.
Более конкретно, следующие определения в iostream (их больше, чем указано в списке и зависят от компилятора) ссылаются на объекты, созданные в стандартной библиотеке, которые затем связываются с вашим кодом:
extern istream &cin;
extern ostream &cout;
extern ostream &cerr;
extern ostream &clog;
Обычно файлы заголовков содержат только информацию для компилятора, а не реальный код. Например:
struct foo {
int x;
};
Подобные определения структур часто появляются в заголовках, но на самом деле они не вызывают генерации кода, так как они дают компилятору только информацию о том, как обрабатывать 'foo', если он увидит это позже. Если он не видит foo, информация теряется после завершения компиляции.
Фактически, наличие всего, что генерирует код, обычно приводит к ошибке. Например:
void foo() {
printf("bar!\n");
}
Если это находится в заголовке и включается в два файла .c, функция foo ()
будет сгенерирована дважды . Это вызовет ошибку по ссылке. Ошибки можно избежать, если для этого есть веская причина. но обычно по возможности избегают генерации кода в заголовках.
Обратите внимание, что одним исключением здесь являются встроенные члены в C ++. Например:
class Foo {
void bar() { /* ... */ }
};
С технической точки зрения bar () создается в каждом файле, который включает этот код. Компилятор использует различные приемы, чтобы избежать ошибки (слабая привязка и т. Д.). Это действительно может увеличить размер исполняемого файла, и это, вероятно, то, что вы видели с
.
Заголовок
содержит несколько объектов, 'std :: cin , 'std :: cout
, std :: cerr
и std :: clog
. Это экземпляры классов, которые имеют нетривиальные конструкторы и деструкторы. Это код, и его необходимо связать. Это то, что увеличивает размер исполняемого файла.
AFAIK,
не поставляется с кодом, поэтому размер исполняемого файла не увеличивается.
В файле iostream объявлены некоторые глобальные объекты:
std :: cout, std :: cerr, std :: cin, которые относятся к типу ostream .
Затем компилятор перенесет этот класс и скомпилирует его прямо в ваш окончательный двоичный файл, значительно увеличив его размер.