Страница 12 из 15 Использование Standard Template Library А как же насчет Standard Template Library (STL)? Насколько она завязана на CRT, можно ли использовать её в сверхмалых проектах? Реализация STL от Dinkumware, поставляемая вместе с VC 5.0 и 6.0, доступна в исходных файлах, так что проблем с компоновкой не возникает. В крайнем случае, всегда можно исправить исходники или сделать какую-нибудь заглушку на #define'ах (перебивающую имена конструкций, тянущих за собой CRT). Другая проблема - в том, что STL повсеместно использует операторы динамического выделения памяти. Как уже говорилось, это вызывает необходимость собственной реализации операторов new/delete. Это можно сделать, например, так (идея позаимствована из atlimpl.cpp):
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. |