Анатомия C Run-Time, или Как сделать программу немного меньшего размера - Использование Standard Template Library
ОГЛАВЛЕНИЕ
Использование Standard Template Library
А как же насчет Standard Template Library (STL)? Насколько она завязана на CRT, можно ли использовать её в сверхмалых проектах?
Реализация STL от Dinkumware, поставляемая вместе с VC 5.0 и 6.0, доступна в исходных файлах, так что проблем с компоновкой не возникает. В крайнем случае, всегда можно исправить исходники или сделать какую-нибудь заглушку на #define'ах (перебивающую имена конструкций, тянущих за собой CRT). Другая проблема - в том, что STL повсеместно использует операторы динамического выделения памяти. Как уже говорилось, это вызывает необходимость собственной реализации операторов new/delete. Это можно сделать, например, так (идея позаимствована из atlimpl.cpp):
// stub.cpp - the "mini-CRT" implementation file
void* __cdecl malloc(size_t n)
{
void* pv = HeapAlloc(GetProcessHeap(), 0, n);
return pv;
}
void* __cdecl calloc(size_t n, size_t s)
{
return malloc(n*s);
}
void* __cdecl realloc(void* p, size_t n)
{
if (p == NULL) return malloc(n);
return HeapReAlloc(GetProcessHeap(), 0, p, n);
}
void __cdecl free(void* p)
{
if (p == NULL) return;
HeapFree(GetProcessHeap(), 0, p);
}
void* __cdecl operator new(size_t n)
{
return malloc(n);
}
void __cdecl operator delete(void* p)
{
free(p);
}
Вот пример программы, которая будет спокойно собрана с помощью такого подхода без стартового кода CRT:
#include <windows.h>
#include "stub.cpp"
#include <map>
typedef std::map<int, int> IntMap;
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nShowCmd )
{
IntMap m;
for (int j=0; j<100; j++) m[j*j]=j;
IntMap::iterator i=m.find(49);
MessageBox(0, (i==m.end())?"49 was not found":"49 was found",
"std::map test", MB_OK);
return 0;
}
Для сборки этого примера необходимо использовать следующую командную строку:
cl test.cpp user32.lib kernel32.lib /link /nod /opt:nowin98 /subsystem:windows /entry:WinMain
Библиотека импорта kernel32.lib необходима для функций работы с Win32-кучей.
Что касается других реализаций STL, предоставлю слово Павлу Блудову:
"Страшная тайна STL от SGI и HP в том, что им совершенно не нужна CRT.
С двумя оговорками:
- Не используется C++ Exception Handling
- (Вытекает из первой) определен макрос __THROW_BAD_ALLOC, например, так:
#ifndef _CPPUNWIND
#define __THROW_BAD_ALLOC \
::MessageBox(NULL, _T("STL: Out of memory."), NULL, MB_OK | MB_ICONSTOP); \
::ExitProcess(-5);
#endif _CPPUNWIND
#include <stl_config.h>
если посмотреть на __THROW_BAD_ALLOC, то он являет собой
#define __THROW_BAD_ALLOC fprintf(stderr, "out of memory\n"); exit(1)
именно эта строчка, и никакая другая, нуждается в CRT. Ну, если быть совсем точным, std::string'у может понадобиться CRT. Тут уж ничего не попишешь. Используйте WTL::CString.
Павел."
Слова о std::string в полной мере справедливы и для реализации STL от Dinkumware. Если вы ищете реализацию полноценного строкового класса, не использующего стартовый код CRT, советую взглянуть на CascString в составе библиотеки ascLib.