MSVC 2010
Класс CAtlArray.
Метод SetAtGrow и т.п.
Для увеличения размера вызывается SetCount.
SetCount вызывает GrowBuffer.
GrowBuffer создает новый буфер, и для переноса данных из старого буфера в новый вызывает RelocateElements из класса Traits, указанного вторым аргументом CAtlArray.
Реализация RelocateElements по-умолчанию для произвольных типов выполняет memmove, т.е. побитное копирование.
(traits специфицируется для некоторых типов — стринг, вариант, guid и встроенные целочисленные типы, но там переопределяется только хеширование и сравнение).
Получается, CAtlArray "из коробки" непригоден для использования и требует допиливания?
Здравствуйте, rus blood, Вы писали:
RB>Класс CAtlArray, для увеличения размера вызывается SetCount, SetCount вызывает GrowBuffer. RB>GrowBuffer создает новый буфер, и для переноса данных из старого буфера в новый вызывает RelocateElements из класса Traits, указанного вторым аргументом CAtlArray. RB>Реализация RelocateElements по-умолчанию для произвольных типов выполняет memmove, т.е. побитное копирование. RB>(traits специфицируется для некоторых типов — стринг, вариант, guid и встроенные целочисленные типы, но там переопределяется только хеширование и сравнение). RB>Получается, CAtlArray "из коробки" непригоден для использования и требует допиливания?
Допиливать (=указывать другой Traits, в котором переопределено RelocateElements) нужно только в одном случае "у тебя в классе есть адреса или ссылки на свои же поля".
Случай довольно редкий, например я сходу не могу назвать ни один класс в ATL/WTL, который бы ломался от переноcа методом memmove.
Performance penalty при использовании "честного" преремещения (=вызвать in-place copy constructor, потом деструктор у старого объекта) будет для всех классов, которые ты складываешь в CAtlArray. И на этапе компиляции это не выяснить.
Дизайнеры ATL когда-то решили, что для них производительность важнее всего остального (в разумных пределах конечно).
Именно поэтому ATL-коллекции (кроме строк: когда последний раз исследовал вопрос, они были ощутимо быстрее в STL, думаю это потому шо внутри CString всегда один NULL-terminated кусок, а std::wstring делает один NULL-terminated кусок только при вызове c_str() ) обычно выигрывают у STL по производительности, а иногда прям в два раза выигрывают. Например сделайте тест "добавить миллион небольших элементов в связный список или в hash map" — ATL будет примерно вдвое быстрее в release build, и во много раз быстрее в debug build.