Russian Qt Forum
Апрель 30, 2024, 19:37 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: Работа с контейнерами - терзают сомненья  (Прочитано 13195 раз)
vanessa
Гость
« : Январь 18, 2010, 23:13 »

В силу не очень хорошего знания С++ хочу задать вопрос
Код:
#include <QtCore>
#include <QDebug>


QVector<int> getValue()
{
    QVector<int> vec;
    vec << 10 << 11 << 12;
    return vec;
}



int main(int argc,char **argv)
{
    QVector<int> a;
    a << 1 << 2 << 3;

    a=getValue();
    qDebug()<<a;

    return 0;
}


не будет ли утечки памяти в строчке
    a=getValue();
тоесть будет ли удалена или перераспределена память используемая для хранения значений a в момент присвоения этой переменной нового значения ?
и вообще можно ти делать такие функции, которые будут приниматть или возвращать контейнеры, не является ли это плохим стилем ?

Записан
Пантер
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 5876


Жаждущий знаний


Просмотр профиля WWW
« Ответ #1 : Январь 18, 2010, 23:25 »

Утечки не будет.
Записан

1. Qt - Qt Development Frameworks; QT - QuickTime
2. Не используйте в исходниках символы кириллицы!!!
3. Пользуйтесь тегом code при оформлении сообщений.
lit-uriy
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3880


Просмотр профиля WWW
« Ответ #2 : Январь 18, 2010, 23:37 »

>>будет ли удалена или перераспределена память используемая для хранения значений a
В данном случае будет, т.к. в контейнере хранятся значения. Подробности о том, как разные типы данных хранятся в контейнерах смотри тут

>>не является ли это плохим стилем ?
Посмотри на QObject::findChildren и ей подобные функции.
Записан

Юра.
niXman
Гость
« Ответ #3 : Январь 19, 2010, 00:52 »

Цитировать
В данном случае будет, т.к. в контейнере хранятся значения.
поясните.
Записан
lit-uriy
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3880


Просмотр профиля WWW
« Ответ #4 : Январь 19, 2010, 08:20 »

еже либ там были указатели на объекты, то объекты надо было бы прибивать руками, т.к. контейнер сам этим не занимается.
Записан

Юра.
Marat(Qt)
Гость
« Ответ #5 : Январь 20, 2010, 19:27 »

еже либ там были указатели на объекты, то объекты надо было бы прибивать руками, т.к. контейнер сам этим не занимается.
Код:
QVector<T> &QVector<T>::operator=(const QVector<T> &v)
{
    v.d->ref.ref();
    if (!d->ref.deref())
        free(d);
    d = v.d;
    if (!d->sharable)
        detach_helper();
    return *this;
}
А как такое объяснить? Вектор очищяется перед заполнением новыми значениями, следовательно - нет утечки
Записан
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3258


Просмотр профиля
« Ответ #6 : Январь 20, 2010, 20:26 »

удаляется d_ptr, а данные - нет
Записан
lit-uriy
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3880


Просмотр профиля WWW
« Ответ #7 : Январь 20, 2010, 20:40 »

>>Вектор очищяется
именно вектор, а не объекты созданные с помощью new.

Из документации по Tulip:
Цитировать
Контейнеры Tulip содержат значения. Если вы хотите использовать список в котором каждое значение - это QWidget *, используйте QList<QWidget *>.

Новые контейнеры не поддерживают автоудаления. Мы обнаружили, что на практике, единственным случаем, где нужно автоудаление является ситуация, где в контейнере содержатся значения, а не указатели (например, QList<int>, а не QList<int *>). Если вы хотите удалить все элементы, хранящиеся в контейнере, используйте qDeleteAll().

Цитировать
Код
C++ (Qt)
QList<Employee *> list;
list.append(new Employee("Blackpool", "Stephen"));
list.append(new Employee("Twist", "Oliver"));
 
qDeleteAll(list.begin(), list.end());
list.clear();
« Последнее редактирование: Январь 20, 2010, 20:43 от lit-uriy » Записан

Юра.
SABROG
Гость
« Ответ #8 : Январь 20, 2010, 21:04 »

Вместо хранения указателей в контейнерах вполне можно использовать QSharedPointer, тогда при вызове clear() указатели удаляться автоматически.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #9 : Январь 21, 2010, 21:30 »

и вообще можно ти делать такие функции, которые будут приниматть или возвращать контейнеры, не является ли это плохим стилем ?
Хотя делать такие ф-ции не запрещено, это является плохим стилем (и не стоит смотреть/уповать на то что Qt это частенько делает). Память будет освобождена (как обсуждалось выше) но ценой выполнения очень многих действий, в Вашем конкретном примере Вы погасили скорость выполнения в несколько раз без всякой необходимости. По классике это звучит примерно так:

Цитировать
Настоятельно рекомендуется передавать структуры по указателю/ссылке, хотя это и связано с потенциальными ошибками
 
Это совсем нетрудно и никак не диннее, например:
Код:
void addValue( QVector<int> & vec )
{
    vec << 10 << 11 << 12;
}
Записан
vanessa
Гость
« Ответ #10 : Январь 21, 2010, 22:00 »


Настоятельно рекомендуется передавать структуры по указателю/ссылке, хотя это и связано с потенциальными ошибками
 
Это совсем нетрудно и никак не диннее, например:
Код:
void addValue( QVector<int> & vec )
{
    vec << 10 << 11 << 12;
}

[/quote]

Спасибо за ответы. Я почему спрашивал, из-за недостаточности опыта. Вот например если этот вектор есть закрытим членом какого-то класса. Нас учили (не знаю правильно или нет) что доступ к данным должен осуществляться с помощью соответствующих функций. Я могу вернуть указатель  на данные, но не будет ли правильнее вернуть сами данные ?

Записан
BRE
Гость
« Ответ #11 : Январь 21, 2010, 22:03 »

(и не стоит смотреть/уповать на то что Qt это частенько делает).
Разработчики Qt сначала потрудились и реализовали все классы-контейнеры с механизмом Implicit Sharing. Поэтому объекты этих классов можно спокойно возвращать из функций и никакого оверхеда это не вызовет.
Другое дело, что с любыми объектами так делать не всегда хорошо...

Настоятельно рекомендуется передавать структуры по указателю/ссылке, хотя это и связано с потенциальными ошибками
   
Кем рекомендуется?
« Последнее редактирование: Январь 21, 2010, 22:19 от BRE » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #12 : Январь 22, 2010, 21:57 »

Я могу вернуть указатель  на данные, но не будет ли правильнее вернуть сами данные ?
Правильнее то как нужно в задаче  Улыбающийся Возвращая "сами данные" Вы тем самым вызываете их копирование (и последующее удаление). А это совсем недешево, особенно для сложных данных. Если Вы делаете это намеренно/осознанно (да, здесь нужна копия) - на здоровье. А иначе надо использовать константные указатели и/или ссылки. 

Разработчики Qt сначала потрудились и реализовали все классы-контейнеры с механизмом Implicit Sharing.
Механизм Implicit Sharing (или shallow copy) встроен в конкретные классы, контейнеры сами по себе ничего не решают. Например:

QString умеет создавать "быстрые копии"
Код:
QVector <QString> vec;
..
QString s = vec[0];   // это не выделяет память (пока)
..
}  //  здесь вызовется  деструктор s который сработает быстро (если s не менялось)   

А std::string не умеет
Код:
QVector <std::string> vec;
..
std::string s = vec[0];   // выделение памяти и копирование данных (+ время)
..
}  //  деструктор s освобождает память (+время)
Т.е. тот же самый контейнер может давать очень разную производительность в зависимости от "начинки".

Поэтому объекты этих классов можно спокойно возвращать из функций и никакого оверхеда это не вызовет.
"Никакого" - это для языков типа Clipper, с которого, возможно, Вы начинали  Улыбающийся Расходы все равно будут и для скоростных задач они все равно неприемлемы. Др. дело что они будут намного меньше по сравнению с "копированием в лоб" напр. как в STL. Здесь конечно, Qt смотрится посильнее.
Записан
BRE
Гость
« Ответ #13 : Январь 22, 2010, 22:16 »

Возвращая "сами данные" Вы тем самым вызываете их копирование (и последующее удаление). А это совсем недешево, особенно для сложных данных.
Мы говорим о возвращении из функции Qt-контейнеров, поэтому никакого копирования при этом не происходит. Копирование будет выполнено только при попытке изменения данных в результирующем контейнере.

Механизм Implicit Sharing (или shallow copy) встроен в конкретные классы, контейнеры сами по себе ничего не решают. Например:
Данные контейнера хранятся в разделяемом-объекте, так же как и данные QString. Поэтому, при присвоении/возвращении/передаче в параметрах контейнера реально передается  только указатель на приватный объект.
Никакого дополнительного копирования данных не происходит, до момента их изменения.

QString умеет, std::string нет, поэтому я написал:
Цитировать
Другое дело, что с любыми объектами так делать не всегда хорошо...
Но, вопрос был про Qt-контейнеры, поэтому спокойно можно.

"Никакого" - это для языков типа Clipper, с которого, возможно, Вы начинали  Улыбающийся Расходы все равно будут и для скоростных задач они все равно неприемлемы. Др. дело что они будут намного меньше по сравнению с "копированием в лоб" напр. как в STL. Здесь конечно, Qt смотрится посильнее.
Начинал я с ассемблера для 6502, Клипер обошел меня стороной.  Улыбающийся
Расходы будут такие же, как возвращение ссылки/указателя.
Для скоростных задач самое важное оптимизация алгоритмов, а не попытки оптимизировать код реализующий медленный алгоритм, путем отказа от конструкторов/деструкторов и т.д.
« Последнее редактирование: Январь 22, 2010, 22:26 от BRE » Записан
vanessa
Гость
« Ответ #14 : Январь 22, 2010, 22:18 »

А иначе надо использовать константные указатели и/или ссылки. 

тоесть  моя функция, если б она была членом класса была бы такая
Код:
const QVector<int>& getValue();
?

Записан
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.076 секунд. Запросов: 22.