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

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

Страниц: 1 2 [3] 4 5 ... 7   Вниз
  Печать  
Автор Тема: Контейнерные классы  (Прочитано 42092 раз)
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #30 : Февраль 08, 2014, 19:51 »

Допустим мне нужна телефонная книга. Я задаю имя и получаю список телефонов. Что лучше выбрать QMultiMap или QMultiHash?
А Вы собираетесь ее пополнять/редактировать? Если нет, то оба выбора - не лучшие
Записан
Johnik
Крякер
****
Online Online

Сообщений: 339


Просмотр профиля
« Ответ #31 : Февраль 08, 2014, 23:04 »

Так вы почитали в чем разница между Map и Hash?
Если нужно только искать, то при таких объемах (небольших) разницы вы не увидите. А вот если вы захотите пробегаться по всей коллекции, то разницу вы увидите сразу. Пробуйте. Подмигивающий
Поддерживаю. И добавлю, на хабре пробегала статья: QMap vs. QHash: небольшой бенчмарк
Записан
8Observer8
Гость
« Ответ #32 : Февраль 10, 2014, 12:47 »

К Map и Hash я позже вернусь. Для меня это на данный момент сложновато.

Я сейчас с vector'ом разбираюсь. В следующей программке метод size() будет вызнан один раз или каждый раз пока работает цикл?

Код:
#include <iostream>
#include <vector>
using namespace std;

int main(int argc, char *argv[]) {

    vector<int> myvector {1, 2, 3, 4, 5, 6, 7, 8};

    cout << "myvector: ";
    for (size_t i = 0; i < myvector.size(); ++i) {
        cout << " " << myvector[i];
    }
    cout << endl;

    return 0;
}
« Последнее редактирование: Февраль 10, 2014, 12:56 от 8Observer8 » Записан
OKTA
Гость
« Ответ #33 : Февраль 10, 2014, 12:55 »

Look at this  Подмигивающий
http://codepad.org/BBfGJchj
Записан
8Observer8
Гость
« Ответ #34 : Февраль 10, 2014, 13:05 »


Я думал, тут хитрость есть, что для контейнеров один раз будет вызываться, так как если контейнер большой, то вызов size() будет очень дорогим.

На форумах часто попадаются примеры, где size вызывается в цикле

Значит размер буду вычислять до цикла  Подмигивающий Спасибо! Улыбающийся

Код:
#include <iostream>
#include <vector>
using namespace std;

int main(int argc, char *argv[]) {

    vector<int> myvector {1, 2, 3, 4, 5, 6, 7, 8};

    size_t size = myvector.size();
   
    cout << "myvector: ";
    for (size_t i = 0; i < size; ++i) {
        cout << " " << myvector[i];
    }
    cout << endl;

    return 0;
}
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #35 : Февраль 10, 2014, 13:30 »

Я думал, тут хитрость есть, что для контейнеров один раз будет вызываться, так как если контейнер большой, то вызов size() будет очень дорогим.
Улыбающийся Почти для всех контейнеров вызов size() очень дешев, практически бесплатный, поэтому обычно локальную переменную не заводят. Из исключений могу вспомнить только std::list

А вот типичная ловушка с вектором

Код
C++ (Qt)
std::vector <int> vec;
// QVector <int> vec;
// как-то заполнили вектор
...
size_t count = vec.size();
for (size_t i = 0; i < count; ++i) {
int & val = vec[i];
if (val < 0) vec.push_back(val);
val = 0;
}
Записан
8Observer8
Гость
« Ответ #36 : Февраль 10, 2014, 13:39 »

Почти для всех контейнеров вызов size() очень дешев, практически бесплатный, поэтому обычно локальную переменную не заводят. Из исключений могу вспомнить только std::list

Спасибо! Я думал у size линейная сложность Улыбающийся Ан нет - константная: http://www.cplusplus.com/reference/vector/vector/size/
Записан
8Observer8
Гость
« Ответ #37 : Февраль 10, 2014, 14:40 »

Вот в в этой книге http://www.wrox.com/WileyCDA/WroxTitle/Professional-C-2nd-Edition.productCd-0470932449.html постоянно делается упор на C++11, поэтому лучше по-современному, вот так:

Код:
#include <iostream>
#include <vector>
using namespace std;

int main(int argc, char *argv[]) {

    vector<int> myvector {1, 2, 3, 4, 5, 6, 7, 8};
    
    cout << "myvector: ";
    for (auto iter = myvector.cbegin();
            iter != myvector.cend(); ++iter) {
        cout << " " << *iter;
    }
    cout << endl;

    cout << "myvector: ";
    for (auto& i : myvector) {
        cout << " " << i;
    }
    cout << endl;

    return 0;
}
« Последнее редактирование: Февраль 10, 2014, 14:45 от 8Observer8 » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #38 : Февраль 10, 2014, 15:53 »

..поэтому лучше по-современному, вот так:
Ах как резво Вы хватаете "вершки" Улыбающийся Ловушку из предыдущего поста разберите, толку больше будет
Записан
OKTA
Гость
« Ответ #39 : Февраль 10, 2014, 15:59 »

Спасибо! Я думал у size линейная сложность Улыбающийся Ан нет - константная: http://www.cplusplus.com/reference/vector/vector/size/

В общем случае, константная сложность не дает гарантии, что операция будет работать быстрее по сравнению с операцией с линейной сложностью, на сколько я знаю  Улыбающийся
Записан
Fat-Zer
Гость
« Ответ #40 : Февраль 10, 2014, 17:47 »

Немного запоздало, про то с чего тема начиналась...

Текст из книги Макса Шлее "Профессиональное программирование на С++. Qt 4.8":

Цитировать
При  создании объекта  класса  QMap<K,T>
  нужно передать  его  размер в конструктор. Этот
размер не является, как это принято в других контейнерных классах, размером, ограничи-
вающим максимальное  количество элементов,  а представляет  собой количество позиций.
Количество позиций должно быть больше количества элементов, ожидаемых для хранения,
иначе поиск элементов в словаре будет проводиться недостаточно эффективно. Желатель-
но, чтобы это значение относилось к разряду простых чисел, т. к. в этом случае размещение
элементов будет более  удобным  (см. приложение 2)

Мне тут каждое предложение непонятно.
В Qt3 было несколько контейнеров Q{Int,Ascii,чего-то-там-ещё,}Dict, так это как раз про них. Передаваемый размер там задавал размер хеш-таблицы...
Дальше взял посмотреть книгу тов. Шлее про Qt-3.2... и что бы вы думали? В разделе «Словари» тот же текст слово в слово =)
т.е. мало того, что оно безбожно устарело, так ещё и с ошибкой...

это ещё 5 копеек к тому что стоит больше верить докам и меньше книгам... особенно отечественным...

если что , то на все остальные вопросы «зачем оно нужно» итп — поймёшь, когда прочитаешь, что такое хеш... Подмигивающий
Записан
8Observer8
Гость
« Ответ #41 : Февраль 11, 2014, 13:58 »

Дальше взял посмотреть книгу тов. Шлее про Qt-3.2... и что бы вы думали? В разделе «Словари» тот же текст слово в слово =)
т.е. мало того, что оно безбожно устарело, так ещё и с ошибкой...
Fat-Zer, Спасибо! Как я понял, автор скопировал информацию из старой книги и не поправил. Бывает!

это ещё 5 копеек к тому что стоит больше верить докам и меньше книгам... особенно отечественным...
Да, согласен. Доверяй, но проверяй!

если что , то на все остальные вопросы «зачем оно нужно» итп — поймёшь, когда прочитаешь, что такое хеш...
Да, теория и практика у меня слабы. Стараюсь! Практика + Теория = Гармония

В общем случае, константная сложность не дает гарантии, что операция будет работать быстрее по сравнению с операцией с линейной сложностью, на сколько я знаю  Улыбающийся

Утверждение:
Вставка элемента в середину vector'а (линейная сложность) будет работать гарантированно быстрее, чем доступ по индексу в том же векторе (константная сложность).
« Последнее редактирование: Февраль 11, 2014, 14:39 от 8Observer8 » Записан
8Observer8
Гость
« Ответ #42 : Февраль 11, 2014, 14:04 »

Я думал, тут хитрость есть, что для контейнеров один раз будет вызываться, так как если контейнер большой, то вызов size() будет очень дорогим.
Улыбающийся Почти для всех контейнеров вызов size() очень дешев, практически бесплатный, поэтому обычно локальную переменную не заводят. Из исключений могу вспомнить только std::list

А вот типичная ловушка с вектором

Код
C++ (Qt)
std::vector <int> vec;
// QVector <int> vec;
// как-то заполнили вектор
...
size_t count = vec.size();
for (size_t i = 0; i < count; ++i) {
int & val = vec[i];
if (val < 0) vec.push_back(val);
val = 0;
}

Отличный пример. Где-то подвох, но я его не понял Грустный

Функция:

Код:
void func(vector<int> &vec) {
    size_t count = vec.size();
    for (size_t i = 0; i < count; ++i) {
        int & val = vec[i];
        if (val < 0) vec.push_back(val);
        val = 0;
    }
    cout << "!!!!" << " " << vec.size() << endl;
}

Тест нормально проходит:
Код:
void newtestclass::testFunc_002() {
    vector<int> vec;

    // Заполняем массив
    vec.push_back(-1);
    vec.push_back(3);
    vec.push_back(6);
    vec.push_back(7);
    vec.push_back(1);

    // Обрабатываем элементы массива
    func(vec);

    // Проверяем размер массива
    int expectedSize = 6;
    int actualSize = vec.size();
    CPPUNIT_ASSERT_EQUAL(expectedSize, actualSize);
}
« Последнее редактирование: Февраль 11, 2014, 14:10 от 8Observer8 » Записан
8Observer8
Гость
« Ответ #43 : Февраль 11, 2014, 14:09 »

Извините, неправильно сообщение написал. Исправил.
Записан
OKTA
Гость
« Ответ #44 : Февраль 11, 2014, 14:30 »

Вставка элемента в середину vector'а (линейная сложность) будет работать гарантированно быстрее, чем доступ по индексу в том же векторе (константная сложность). Разве нет?

А почему? Чем больше размер вектора, тем линейная сложность будет больше, разве нет?  Улыбающийся
Записан
Страниц: 1 2 [3] 4 5 ... 7   Вверх
  Печать  
 
Перейти в:  


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