Название: Как правильно работать с контейнером QList? Отправлено: GrieVeR-13 от Апрель 03, 2015, 11:17 Здравствуйте.
Сегодня натолкнулся на неприятную проблему. В моей программе в объекте класса Код: QList<MyClass> myClassList В некоторый момент времени мне понадобилось хранить указатель на один из объектов в листе Код: MyClass *ptr = &myClassList[0] Условие внутри detach() выполняется, когда я вызываю функцию вида Код: computeFunc(GetFunc(myClassList)); Вопрос: я неверно работаю с контейнером? Например, может положено хранить в листе только ссылки? Название: Re: Как правильно работать с контейнером QList? Отправлено: Пантер от Апрель 03, 2015, 11:20 Передавай контейнер по константной ссылке. Зачем его копировать?
Название: Re: Как правильно работать с контейнером QList? Отправлено: __Heaven__ от Апрель 03, 2015, 11:22 Фактически копирования не происходит до первого модифицирования контейнера
Цитировать QList::QList(const QList<T> & other) Constructs a copy of other. This operation takes constant time, because QList is implicitly shared. This makes returning a QList from a function very fast. If a shared instance is modified, it will be copied (copy-on-write), and that takes linear time. Название: Re: Как правильно работать с контейнером QList? Отправлено: Old от Апрель 03, 2015, 11:24 Передавай контейнер по константной ссылке. Зачем его копировать? Перераспределение может произойти и при простом добавлении элементов.2 GrieVeR-13 Не храните в списке значения, храните указатели (желательно умные) на значения. Тогда, даже если список перераспределиться, указатели на значения останутся прежними. Название: Re: Как правильно работать с контейнером QList? Отправлено: __Heaven__ от Апрель 03, 2015, 11:40 Перераспределение может произойти и при простом добавлении элементов. Почему так может произойти? Для std::list я видел схему из * next * prev. В qt механизм хитрее? Название: Re: Как правильно работать с контейнером QList? Отправлено: GrieVeR-13 от Апрель 03, 2015, 11:49 Old: даже при добавлении? Странно, что ранее никогда не сталкивался с таким явлением.
Тем не менее, все равно непонятно почему перераспределения не происходит, если не вкладывать GetFunc в computeFunc. Код: int i = GetFunc(myClassList); Название: Re: Как правильно работать с контейнером QList? Отправлено: Авварон от Апрель 03, 2015, 12:00 Почему так может произойти? Для std::list я видел схему из * next * prev. В qt механизм хитрее? Табличка в начале вам поможет https://marcmutz.wordpress.com/effective-qt/containers/ Название: Re: Как правильно работать с контейнером QList? Отправлено: qate от Апрель 03, 2015, 12:14 В некоторый момент времени мне понадобилось хранить указатель на один из объектов в листе Код: MyClass *ptr = &myClassList[0] храни индекс элемента, а не указатель Название: Re: Как правильно работать с контейнером QList? Отправлено: Igors от Апрель 03, 2015, 12:54 Код: computeFunc(GetFunc(myClassList)); Вопрос: я неверно работаю с контейнером? Например, может положено хранить в листе только ссылки? Название: Re: Как правильно работать с контейнером QList? Отправлено: GrieVeR-13 от Апрель 03, 2015, 14:19 ..Ну Вы же передали копию - он Вам указатель на скопированный элемент и вернул. Все корректно с точки зрения языка. А когда он делал эту копию (сразу или после) - его личное дело. Зачем контейнер по значению передавать? Лень было писать const & - ну получайте проблемы. И QList здесь ни при чем - с любым контейнером то же самое Я чуть выше добавил, что указатель - на оригинал. Фокус именно в реализации контейнера (см. функцию detach()).Константную ссылку написать забыл. Заинтересовала скорее возникшая проблема, чем метод решения. Всегда считал, что происходит разовая инициализация объекта в листе. Название: Re: Как правильно работать с контейнером QList? Отправлено: __Heaven__ от Апрель 03, 2015, 14:26 operator[] возвращает неконстантную ссылку на элемент контейнера, что подразумевает дальнейшую возможность его редактирования, что в свою очередь вызывает detach() для дублирования.
Название: Re: Как правильно работать с контейнером QList? Отправлено: GrieVeR-13 от Апрель 03, 2015, 15:31 operator[] возвращает неконстантную ссылку на элемент контейнера, что подразумевает дальнейшую возможность его редактирования, что в свою очередь вызывает detach() для дублирования. Да, именно такая ссылка мне и нужна, остается не ясным, с какой целью при определенных условиях дублировать весь список.Всем большая благодарность за оперативные ответы. Название: Re: Как правильно работать с контейнером QList? Отправлено: Igors от Апрель 03, 2015, 16:36 ...остается не ясным, с какой целью при определенных условиях дублировать весь список. Так работает implicit sharing в Qt. Копирование происходит когда возникает необходимость. Название: Re: Как правильно работать с контейнером QList? Отправлено: lit-uriy от Апрель 03, 2015, 20:20 GrieVeR-13, рекомендую почитать ПОЛНОСТЬЮ, документацию времён Qt4.6, на русском:
http://www.doc.crossplatform.ru/qt/4.6.x/containers.html особо обратите внимание на раздел об итераторах, там много тонких мест указано, ну и разумеется раздел "Стратегии увеличения размера" |