Pull to refresh

Comments 23

Да, похоже не то. В стандарте по этому пункту особо разбираться не стал, ведь на всех трех компиляторах, где я запускал этот код в режиме --std=c++11 подсчет ссылок присутствовал.
Буду благодарен, если подскажете как его отключить.
Мм, тут подсказывают что строки, совместимые с с++11 появятся в следующей версии библиотеки. А в текущей версии совместимыми являются __gnu_cxx::__versa_string из #include <ext/vstring.h>. Сразу же попробовал но похоже меня постигло разочарование :( в __versa_string используютя анонимные объединения, не позволяющие использовать в качестве символов типы имеющие конструктор. Но как оказалось это можно с -std=gnu++11 и таки да, подсчет ссылок отключился.
Можете пожайлуйста дать ссылку на этот материал (с++11 совместимые строки). Интересно почтитать, что будет нового в следующей версии, а changelog GCC-4.9 молчит по поводу libstdc++.
Нет не забыл. char_traits определяют операции с символами и массивами символов. Ну и он параметризируемый. Т.е. basic_string использутет трайт char_traits. Вот вам пример из файла 4.7.2/bits/char_traits.h реализация одного из 14 методов структуры char_traits.
      static _GLIBCXX_CONSTEXPR bool
      lt(const char_type& __c1, const char_type& __c2)
      { return __c1 < __c2; }

Тут будет использован operator<(const X&).
Ну и кроме того, если бы были какие-либо несоответствия с операциями, то код бы просто не компилировался.
Заполняющий конструктор так вообще удивил — откуда-то взялись дополнительные копирования и деструкторы.
Они взялись из-за передачи трассера по значению в подпрограммы. Что характерно, если бы тип НЕ был трассером, то компилятор все оптимизировал бы и заинлайнил, и никаких дополнительных копирований не происходило бы.
Неожиданно, результат для resize получился значительно хуже чем для reserve
Для меня — ожидаемо.
reserve меняет размер выделенного под строку буфера, но не меняет саму строку.
resize же меняет длину строки, для чего должен дописать в конец нужное число символов.
деструкторы для символов не вызываются

А типа, должны были бы?

Мне кажется, у вас вообще результаты получились сильно далеки от правды из-за того, что компилятор не оптимизировал (или по-другому оптимизировал) обращение с классом — с элементарным типом char там может всё совсем по-другому быть.
Для полноценного контейнера должны были, а для строки мне было неизвестно. Теперь ясно, что не вызываются.

Тут не в оптимизации одного алгоритма, дело в сравнении двух. Если количество операций в неоптимизированном варианте меньше, то после оптимизации скорее всего быстрее будет алгоритм с меньшим количеством операций.
Да, возможно всякие выравнивания и детали реализации съедят разницу в скоростях, но зато подсчет операций трассером не завист ни от платформы, ни от уровня оптимизации.
Таки до конца не осознал, надо еще пару раз перечитать.

Первый аспект который я не понял. class X это заменитель типа char? т.е. в строке
xs s1((X*)«1234567890»);,

X* x = (X*) «1234567890», x будет воспринят как указатель на массив из элементов X?
Еще я немного удивлен тем что не используются операции типа memcpy для копирования _CharT* _M_p.

class X — это заменитель char, бинарно совместимый с ним. Вся его полезная нагрузка — это подсчет вызовов конструкторов, деструкторов и прочих операций.

А операции типа memcpy для копирования X не используются, поскольку не указаны в общей реализации char_traits. Операции над строкой char, конечно же, ускоряются.
А пробовали сравнивать различные std библиотеки? Я на вскидку знаю три, умеющих С++11, это libstdc++ из gcc, libcxx из clang и msvcшная реализация, которая глубоко привязана к компилятору.
Локально не пробовал. Однако, тут есть сервис предлагающий компиляцию разными компиляторами (g++,intel,clang) врядли они используют одну и ту же реализацию, хотя не факт конечно. Так вот, на этом сервисе результаты у этих трех компиляторов одинаковые.

msvc у меня нет, возможно кто-нибудь из хабраюзеров сможет скачать исходник и выложить тут получившуюся табличку(она прям в html генерится).
Потому, что надо вот так собирать
-std=c++11 -Wall -W -pedantic -O2  -stdlib=libc++

Но тот сервис такое не поддерживает. А без этого флага они все три используют libstdc++
Ясно, спасибо. Как настрою у себя clang — выложу результат.
C нативной clang библиотекой не собирается:

$ clang++ -std=c++11 -Wall -W -pedantic -O2  -stdlib=libc++ ./test.cpp

/usr/include/c++/v1/string:1134:31: error: attempt to use a deleted function
    _LIBCPP_INLINE_VISIBILITY basic_string()
...
fatal error: too many errors emitted, stopping now 
Судя по всему ему не нравится, что этот трейсер не POD тип.
msvc из vs2012:
error C2621: member 'std::_String_val<_Val_types>::_Bxty::_Buf' of union 'std::_String_val<_Val_types>::_Bxty' has copy constructor
        with
        [
            _Val_types=std::_Simple_types<tracer::X>
        ]
У вас в методике тестирования принципиально заложен undefined behavior. Читаем C++11 [strings]:

> This Clause describes components for manipulating sequences of any non-array POD (3.9) type.

Ваш класс совсем не POD. Поэтому все измерения не имеют никакого смысла, это всё UB.
Мм, признаться редко стандарт читаю. Действительно в обоих стандартах POD типы не должны иметь как минимум user-defined конструкторов.
Ну чтож… Значит это UB и приходится полагаться на компилятор.
а в какой главе «C++ Templates: The Complete Guide» написано про трассировщик?
Sign up to leave a comment.

Articles