Название: Работа с контейнерами - терзают сомненья Отправлено: vanessa от Январь 18, 2010, 23:13 В силу не очень хорошего знания С++ хочу задать вопрос
Код: #include <QtCore> не будет ли утечки памяти в строчке a=getValue(); тоесть будет ли удалена или перераспределена память используемая для хранения значений a в момент присвоения этой переменной нового значения ? и вообще можно ти делать такие функции, которые будут приниматть или возвращать контейнеры, не является ли это плохим стилем ? Название: Re: Работа с контейнерами - терзают сомненья Отправлено: Пантер от Январь 18, 2010, 23:25 Утечки не будет.
Название: Re: Работа с контейнерами - терзают сомненья Отправлено: lit-uriy от Январь 18, 2010, 23:37 >>будет ли удалена или перераспределена память используемая для хранения значений a
В данном случае будет, т.к. в контейнере хранятся значения. Подробности о том, как разные типы данных хранятся в контейнерах смотри тут (http://www.doc.crossplatform.ru/qt/4.4.3/containers.html#the-container-classes) >>не является ли это плохим стилем ? Посмотри на QObject::findChildren и ей подобные функции. Название: Re: Работа с контейнерами - терзают сомненья Отправлено: niXman от Январь 19, 2010, 00:52 Цитировать В данном случае будет, т.к. в контейнере хранятся значения. поясните.Название: Re: Работа с контейнерами - терзают сомненья Отправлено: lit-uriy от Январь 19, 2010, 08:20 еже либ там были указатели на объекты, то объекты надо было бы прибивать руками, т.к. контейнер сам этим не занимается.
Название: Re: Работа с контейнерами - терзают сомненья Отправлено: Marat(Qt) от Январь 20, 2010, 19:27 еже либ там были указатели на объекты, то объекты надо было бы прибивать руками, т.к. контейнер сам этим не занимается. Код: QVector<T> &QVector<T>::operator=(const QVector<T> &v) Название: Re: Работа с контейнерами - терзают сомненья Отправлено: Авварон от Январь 20, 2010, 20:26 удаляется d_ptr, а данные - нет
Название: Re: Работа с контейнерами - терзают сомненья Отправлено: lit-uriy от Январь 20, 2010, 20:40 >>Вектор очищяется
именно вектор, а не объекты созданные с помощью new. Из документации по Tulip: Цитировать Контейнеры Tulip содержат значения. Если вы хотите использовать список в котором каждое значение - это QWidget *, используйте QList<QWidget *>. Новые контейнеры не поддерживают автоудаления. Мы обнаружили, что на практике, единственным случаем, где нужно автоудаление является ситуация, где в контейнере содержатся значения, а не указатели (например, QList<int>, а не QList<int *>). Если вы хотите удалить все элементы, хранящиеся в контейнере, используйте qDeleteAll(). Цитировать Код
Название: Re: Работа с контейнерами - терзают сомненья Отправлено: SABROG от Январь 20, 2010, 21:04 Вместо хранения указателей в контейнерах вполне можно использовать QSharedPointer, тогда при вызове clear() указатели удаляться автоматически.
Название: Re: Работа с контейнерами - терзают сомненья Отправлено: Igors от Январь 21, 2010, 21:30 и вообще можно ти делать такие функции, которые будут приниматть или возвращать контейнеры, не является ли это плохим стилем ? Хотя делать такие ф-ции не запрещено, это является плохим стилем (и не стоит смотреть/уповать на то что Qt это частенько делает). Память будет освобождена (как обсуждалось выше) но ценой выполнения очень многих действий, в Вашем конкретном примере Вы погасили скорость выполнения в несколько раз без всякой необходимости. По классике это звучит примерно так:Цитировать Настоятельно рекомендуется передавать структуры по указателю/ссылке, хотя это и связано с потенциальными ошибками Это совсем нетрудно и никак не диннее, например: Код: void addValue( QVector<int> & vec ) Название: Re: Работа с контейнерами - терзают сомненья Отправлено: vanessa от Январь 21, 2010, 22:00 Настоятельно рекомендуется передавать структуры по указателю/ссылке, хотя это и связано с потенциальными ошибками Это совсем нетрудно и никак не диннее, например: Код: void addValue( QVector<int> & vec ) [/quote] Спасибо за ответы. Я почему спрашивал, из-за недостаточности опыта. Вот например если этот вектор есть закрытим членом какого-то класса. Нас учили (не знаю правильно или нет) что доступ к данным должен осуществляться с помощью соответствующих функций. Я могу вернуть указатель на данные, но не будет ли правильнее вернуть сами данные ? Название: Re: Работа с контейнерами - терзают сомненья Отправлено: BRE от Январь 21, 2010, 22:03 (и не стоит смотреть/уповать на то что Qt это частенько делает). Разработчики Qt сначала потрудились и реализовали все классы-контейнеры с механизмом Implicit Sharing. Поэтому объекты этих классов можно спокойно возвращать из функций и никакого оверхеда это не вызовет.Другое дело, что с любыми объектами так делать не всегда хорошо... Настоятельно рекомендуется передавать структуры по указателю/ссылке, хотя это и связано с потенциальными ошибками Кем рекомендуется? Название: Re: Работа с контейнерами - терзают сомненья Отправлено: Igors от Январь 22, 2010, 21:57 Я могу вернуть указатель на данные, но не будет ли правильнее вернуть сами данные ? Правильнее то как нужно в задаче :) Возвращая "сами данные" Вы тем самым вызываете их копирование (и последующее удаление). А это совсем недешево, особенно для сложных данных. Если Вы делаете это намеренно/осознанно (да, здесь нужна копия) - на здоровье. А иначе надо использовать константные указатели и/или ссылки. Разработчики Qt сначала потрудились и реализовали все классы-контейнеры с механизмом Implicit Sharing. Механизм Implicit Sharing (или shallow copy) встроен в конкретные классы, контейнеры сами по себе ничего не решают. Например:QString умеет создавать "быстрые копии" Код: QVector <QString> vec; А std::string не умеет Код: QVector <std::string> vec; Поэтому объекты этих классов можно спокойно возвращать из функций и никакого оверхеда это не вызовет. "Никакого" - это для языков типа Clipper, с которого, возможно, Вы начинали :) Расходы все равно будут и для скоростных задач они все равно неприемлемы. Др. дело что они будут намного меньше по сравнению с "копированием в лоб" напр. как в STL. Здесь конечно, Qt смотрится посильнее.Название: Re: Работа с контейнерами - терзают сомненья Отправлено: BRE от Январь 22, 2010, 22:16 Возвращая "сами данные" Вы тем самым вызываете их копирование (и последующее удаление). А это совсем недешево, особенно для сложных данных. Мы говорим о возвращении из функции Qt-контейнеров, поэтому никакого копирования при этом не происходит. Копирование будет выполнено только при попытке изменения данных в результирующем контейнере.Механизм Implicit Sharing (или shallow copy) встроен в конкретные классы, контейнеры сами по себе ничего не решают. Например: Данные контейнера хранятся в разделяемом-объекте, так же как и данные QString. Поэтому, при присвоении/возвращении/передаче в параметрах контейнера реально передается только указатель на приватный объект.Никакого дополнительного копирования данных не происходит, до момента их изменения. QString умеет, std::string нет, поэтому я написал: Цитировать Другое дело, что с любыми объектами так делать не всегда хорошо... Но, вопрос был про Qt-контейнеры, поэтому спокойно можно."Никакого" - это для языков типа Clipper, с которого, возможно, Вы начинали :) Расходы все равно будут и для скоростных задач они все равно неприемлемы. Др. дело что они будут намного меньше по сравнению с "копированием в лоб" напр. как в STL. Здесь конечно, Qt смотрится посильнее. Начинал я с ассемблера для 6502, Клипер обошел меня стороной. :)Расходы будут такие же, как возвращение ссылки/указателя. Для скоростных задач самое важное оптимизация алгоритмов, а не попытки оптимизировать код реализующий медленный алгоритм, путем отказа от конструкторов/деструкторов и т.д. Название: Re: Работа с контейнерами - терзают сомненья Отправлено: vanessa от Январь 22, 2010, 22:18 А иначе надо использовать константные указатели и/или ссылки. тоесть моя функция, если б она была членом класса была бы такая Код: const QVector<int>& getValue(); Название: Re: Работа с контейнерами - терзают сомненья Отправлено: BRE от Январь 22, 2010, 22:25 тоесть моя функция, если б она была членом класса была бы такая Так ты возвращаешь ссылку на локальный объект, который разрушиться при выходе из функции.Код: const QVector<int>& getValue(); Для Qt-контейнеров, та функция, которую ты привел в первом посте, абсолютно корректная. Никакого копирования данных происходить не будет. Лучше посмотреть самому, как реализованы контейнеры в Qt. Название: Re: Работа с контейнерами - терзают сомненья Отправлено: vanessa от Январь 22, 2010, 22:40 я вообще-то имел ввиду примерно следующее
Код: class blabla Название: Re: Работа с контейнерами - терзают сомненья Отправлено: BRE от Январь 22, 2010, 22:52 если не углубятся в особенности реализации контейнеров Qt то пока будет существовать экземпляр подобного класса его функция getValue(); будет возвращать не сами данные а ссылку на них ? Для подобных случаев лучше возвращать константную ссылку.Но, на самом деле, для Qt-контейнеров это не так важно. Если возвращать по значению, то копирования самих данных все равно происходить не будет. Название: Re: Работа с контейнерами - терзают сомненья Отправлено: Igors от Январь 23, 2010, 21:14 Но, на самом деле, для Qt-контейнеров это не так важно. Если возвращать по значению, то копирования самих данных все равно происходить не будет. Давайте на примерахКод: struct Test { Др. пример Код: struct Test { Ну и конечно, все это только до первой модификации s1. Код: s1 += "a"; Название: Re: Работа с контейнерами - терзают сомненья Отправлено: BRE от Январь 23, 2010, 21:32 Давайте на примерах Давай.Речь идет о издержках при возвращении Qt-контейнеров по значению, т.е.: Код
Я утверждаю, что в этом коде не будут копироваться данные находящиеся в векторе и издержки при таком использовании будут такими же, как и при использовании ссылок (или указателей). Вспомним, что вектор хранит данные в непрерывном блоке и может сообщить нам адрес его первого элемента. Тогда меняем код и смотри: Код
Что же мы видим? И в первом и во втором отладочном выводе адреса реального расположения данных не изменились, как лежали они в одном месте, там и лежат. Чудеса. :o А что же произошло на самом деле? А с этим нужно разобраться самому... Еще удивительным может показаться вывод следующей команды: Код Это к тем издержкам равным передаче ссылки/указателя... Название: Re: Работа с контейнерами - терзают сомненья Отправлено: Igors от Январь 24, 2010, 00:19 Код
Я утверждаю, что в этом коде не будут копироваться данные находящиеся в векторе и издержки при таком использовании будут такими же, как и при использовании ссылок (или указателей). Код: QVector<Test> v = buildVector(); Цитировать ... И "увы" - мы имеем вызванный деструктор (для возвращенного объекта) + оператор присваивания, который примерно = конструктор + деструкторv = buildVector(); Название: Re: Работа с контейнерами - терзают сомненья Отправлено: BRE от Январь 24, 2010, 00:26 Я полностью согласен с Вашим утверждением, но это не имеет никакого отношения к Qt контейнерам, ни к Qt вообще. Все то же самое будет работать с std::vector или просто с любым классом (даже и не контейнером). Как объяснил Rcus такая оптимизация встроена практически во все современные компиляторы. Это имеет прямое отношение к Qt-контейнерам. Можно сделать еще двадцать присвоений и для всех векторов будет одна копия данных.Это легко проверяется с помощью вызова метода: vec.isDetached(), который сообщает, эксклюзивно или нет используются данные. А использует он для этого атомарную переменную ref, содержащую число объектов QVector, которые разделяю данные. Стоит все таки заглянуть в исходники Qt. Насчет того-же самого с std::vector... Не умеет std::vector такого, не умеет... Поэтому, я и написал о том, что Тролли вначале поработали, а теперь могут использовать... Код
Цитировать 0xc44fa0 100 0xc44fa0 100 0xc44fa0 100 ------------------------------------------------- 0xc46cc0 100 0xc46cc0 100 0xc46ed0 100 И "увы" - мы имеем вызванный деструктор (для возвращенного объекта) + оператор присваивания, который примерно = конструктор + деструктор А я и не говорил, что не будет вызван деструктор для локального объекта. Он вызовется, также как и оператор присваивания, только данные копироваться не будут. Скопируется только указатель на внутренний shared-объект.Код А если вызов деструктора, который не делает никаких тяжелых операций, считать большими издержками, то для чего использовать C++? На счет такой "оптимизации" я выше уже высказался. |