Почему std::list больше на С++ 11?

с этим кодом:

#include <iostream>
#include <list>

int main() {
    std::cout << sizeof(std::list<void*>) << std::endl;
};

Я успел заметить, что на GCC 4.7 размер std::list<void*> на C++98 составляет 16 байт, а на C++11 — 24 байта.

Мне было интересно, что изменилось в std::list, что сделало его больше.


person André Puel    schedule 08.04.2012    source источник
comment
С технической точки зрения такое поведение полностью зависит от реализации. Авторы библиотеки могут, если захотят, произвольно решить увеличить класс в 100 раз без каких-либо обоснований. Вероятно, не стоит писать какой-либо код, зависящий от размера списка, равного ровно 16 байтам; что вы делали, когда это действительно вызвало ошибку?   -  person templatetypedef    schedule 08.04.2012
comment
Посмотрите здесь: en.cppreference.com/w/cpp/container/list Вы увидите, что некоторые типы членов изменились в c++11 в std::list.   -  person dexametason    schedule 08.04.2012
comment
Вероятно, они кэшировали размер списка. 24 байта — это три 64-битных значения — начальный указатель, конечный указатель и размер.   -  person Borealid    schedule 08.04.2012
comment
Сам того не заметив, я связал библиотеку C++98 с приложением C++11. В этой библиотеке было несколько встроенных геттеров, которые получали неправильную переменную памяти из-за другого макета памяти класса, вызванного std::list.   -  person André Puel    schedule 08.04.2012
comment
@dexametason: извините, но я не вижу никаких изменений в интерфейсе, которые заставили бы реализацию использовать больший размер. Можете ли вы указать конкретно, что именно вы имели в виду?   -  person templatetypedef    schedule 08.04.2012


Ответы (1)


C++11 требует, чтобы list::size() выполнялось за постоянное время. GCC сделал это возможным, добавив размер в качестве члена данных. GCC не сделал этого для режима C++98, потому что это нарушило бы двоичную совместимость.

Не смешивайте код, скомпилированный в режиме C++98, с кодом, скомпилированным в режиме C++11. Это не работает.

Обновление: по-видимому, разработчики GCC передумали, и соответствие C++11 на данный момент менее важно, чем поддержание совместимости, поэтому list::size() больше не будет выполняться за постоянное время в GCC 4.7.2. Это будет в будущей версии в режимах C++98 и C++11.

person Community    schedule 08.04.2012
comment
В чем сейчас сложность std::list<T>::splice? - person André Puel; 09.04.2012
comment
@André: Это зависит от того, какую перегрузку вы вызываете. Некоторые перегрузки — O(1), некоторые — O(N). - person ildjarn; 09.04.2012
comment
Вам нужно обновить поле размера, поэтому вам нужно подсчитать количество элементов, на которые ссылаются итераторы. - person André Puel; 09.04.2012
comment
Сращивание с двумя и тремя аргументами - это постоянное время, версия с четырьмя аргументами (диапазон итератора в списке from) является линейной по расстоянию диапазона итератора, если только &from == this, и в этом случае это постоянное время. - person emsr; 09.04.2012
comment
@emsr Это то, что требует стандарт, вы проверяли это или вы также проверяли, соответствует ли реализация GCC в этом отношении? - person ; 09.04.2012
comment
@hvd Это требование стандарта. Кроме того, gcc добавил элемент _M_size, который используется для ускорения процесса. Для объединения четырех аргументов и этого != &__x std::distance необходимо использовать для обновления размера. - person emsr; 10.04.2012
comment
@emsr Я спросил, потому что отчет об ошибке, на который я ссылался (который привел к добавлению этого члена), был случаем, когда GCC не соответствовал C ++ 11, поэтому мне любопытно, могут ли быть более тонкие проблемы. - person ; 10.04.2012
comment
Ошибка, на которую вы ссылаетесь, помечена как ИСПРАВЛЕНАЯ, ИСПРАВЛЕННАЯ для gcc-4.7 (только что выпущенная), и код, безусловно, выглядит так, как будто сложность С++ 11 должна соблюдаться. Я не вижу ничего в Bugzilla о том, что соединение не соответствует стандарту. - person emsr; 11.04.2012
comment
Означает ли это, что они отменили все критические изменения ABI в режиме C++11? Вики GCC по-прежнему говорит, что есть поломка: gcc.gnu.org/wiki/Cxx11AbiCompatibility - person Joseph Garvin; 21.09.2012
comment
@hvd: Тогда устранение поломки кажется бессмысленным, кроме как создать еще большую поломку. Если не поддерживается полная совместимость с ABI, все в любом случае должны перекомпилировать при включении коммутатора. - person Joseph Garvin; 22.09.2012
comment
Возможно? Я предположил, что когда вы сказали «Нет», это не означает, что вы говорите как человек, знающий о проектах libstdc++/GCC. Если вы просто комментировали, что мы не знаем, удалили ли они другие изменения ABI на основании того, что @emsr сказал, что это не особенно полезно; вот почему я спросил его. - person Joseph Garvin; 22.09.2012
comment
@hvd: Да, и я хочу сказать, что цель на самом деле не достигается каким-либо полезным образом, если они не удалят их все, на что я надеюсь. - person Joseph Garvin; 23.09.2012
comment
@hvd: Потому что они пересекаются в этом обсуждении. Несовместимости ABI в GCC 4.7.0 и 4.6.x в режиме C++11 связаны с тем, что они реализуют больше поведения C++11. В 4.6.x, даже в режиме C++11, 4.6.x вел себя как C++03 из-за того, что новые функции не были реализованы. Отмена этих изменений в 4.7.2 приводит к исправлению ABI с 4.6.x и уменьшению различий ABI между C++03 и C++11 в 4.7.2, что что на самом деле полезно для людей, занимающихся ABI. Если они передумали в отношении std::list, они должны исправить и другие несовместимости. - person Joseph Garvin; 23.09.2012
comment
@hvd: никого не волнует совместимость GCC с 4.6 по 4.7, когда включен режим С++ 11. Они заботятся о поломке ABI от C++03 до C++11 (и более очевидным является то, что, вероятно, вызвало жалобы, ведущие к отмене изменений в 4.7, хотя я, по общему признанию, размышляю), потому что это мешает большинству людей чтобы включить эту функцию. Это моя точка зрения. - person Joseph Garvin; 23.09.2012
comment
@hvd: Это один из результатов того, что они сделали, а не свидетельство того, что людям не все равно. Я открыт для возможности того, что иногда люди используют плохие формулировки, или не объясняют весь свой мыслительный процесс все время, или могут иметь намерения, отличные от буквы того, что они указали в журнале изменений. Но в любом случае, эта ветка комментариев бесполезна, поэтому я отказываюсь от нее, если только emsr или другой сопровождающий GCC/libstdc++ не вмешается. - person Joseph Garvin; 24.09.2012