Nano Hash - криптовалюты, майнинг, программирование

Векторы разных объектов и работа с их итераторами

У меня есть два вектора разных объектов, и я хотел бы работать с их индексами и итераторами.

Вот код:

bool Database::Birth ( const string & name, const string & addr,
               const string & acc )
{
    SPerson personToAdd = SPerson ( name, addr );
    SAccount accountToAdd = SAccount ( acc );

    SPiter = lower_bound ( SPeople.begin ( ), SPeople.end ( ), personToAdd );

    /* this is the part I can't quite figure out */

    size_t iterDistance = distance ( SPeople.begin ( ), SPiter );
    SAiter = SAccounts.begin ( ) + iterDistance;

    // this is where the segfault is happening 
    if ( ( SPiter -> s_name == name &&
       SPiter -> s_addr == addr ) ||
       SAiter -> s_account == acc ) return false;

    SPeople.insert ( SPiter, personToAdd );
    SAccounts.insert ( SAiter, accountToAdd );

    return true;
}

Должно быть очевидно, что я пытаюсь сделать - я хочу вставить один объект (SPerson) в определенное место в своем векторе (SPeople) и другой объект (SAccount) в свой вектор (SAccounts) под тем же индексом. Можно ли как-то извлечь информацию об «индексе» из итератора?

Я нашел несколько похожих вопросов, но решения очень часто работали с циклами, что мне не нужно (и фактически не могу использовать из-за производительности). Я определенно не могу изменить часть с функцией lower_bound.


  • Вы все делаете правильно - вызов std::distance из SPeople.begin () дает вам индекс. Есть ли проблема, которую вы видите, когда следуете этому подходу? 22.03.2014
  • Вам нужен идентификатор здесь Saiter HERE = SAccounts.begin ( ) + iterDistance;. Кроме этого, это должно работать. 22.03.2014
  • Когда std::distance используется с аргументами RandomAccessIterator, расстояние вычисляется за постоянное время. Так обстоит дело с std::vector итераторами. Однако вы можете просто использовать обычный оператор вычитания - вместо std::distance... 22.03.2014
  • Вау, я удивлен, что я сделал это правильно. Проблема в том, что я вижу старую добрую «Ошибку сегментации» в своем терминале. Я углубился в это, и это происходит из части кода, которую я не публиковал, потому что я думал, что это не имеет значения. Собираюсь обновить вопрос. 22.03.2014
  • Я думаю, что более насущной проблемой кодирования/дизайна является использование имен SPIter и SAIter. Они кажутся переменными, определенными в некоторой охватывающей области класса или пространства имен. Это нехорошо, поскольку приводит к утечке информации из довольно произвольных деталей реализации и может сделать недействительными предположения в другом коде о значениях этих переменных. Вместо этого используйте локальные переменные. 22.03.2014
  • @Cheersandhth.-Альф, спасибо за отзыв - я новичок в этой части кодирования. Я должен реализовать простой класс и его методы, а SPerson и SAccount — его закрытую структуру. Поскольку я работаю с ними в каждом методе, я решил объявить итераторы прямо в классе и назвать их соответственно их векторам. Как правильно это сделать? 22.03.2014
  • @LeaPetrášová: объявить их локально гораздо проще. если современный компилятор, то вы можете просто поставить auto перед инициализирующими назначениями, чтобы превратить их в объявления с инициализаторами. если компилятор не поддерживает auto, то класс может предоставить typedef короткие имена соответствующих типов итераторов, чтобы локальные объявления стали менее подробными. кстати, идея помещения таких переменных в объемлющую область видимости называется переменные блокнота. они в основном повсеместно считаются злом... ;-) 22.03.2014

Ответы:


1

Вам нужно проверить, является ли SPiter действительным, прежде чем вы сможете разыменовать его, так как lower_bound может фактически вернуть SPeople.end(), если искомое значение не меньше, чем любой из элементов. Возможно, используя что-то вроде:

if ( SPiter != SPeople.end ( ) &&
     (( SPiter -> s_name == name &&
     SPiter -> s_addr == addr ) ||
     SAiter -> s_account == acc )) return false;
22.03.2014

2

Вы используете композицию по умолчанию для std::lower_bound со знаком "‹". Поэтому он должен быть правильно перегружен в вашем случае. std::distance дает вам индекс для нижней границы, но, похоже, вам нужно lower_bound + 1.

22.03.2014

3

Это утверждение

size_t iterDistance = distance ( SPeople.begin ( ), SPiter );

дает вам индекс.

Однако учтите, что следующий оператор if

if ( ( SPiter -> s_name == name &&
   SPiter -> s_addr == addr ) ||
   SAiter -> s_account == acc ) return false;

неверно, потому что если элемент не найден, вы пытаетесь получить доступ к векторам за пределами их размеров. Вам нужно добавить еще одно условие

if ( ( SPiter != SPeople.end ( ) && SPiter -> s_name == name &&
   SPiter -> s_addr == addr ) ||
   SAiter -> s_account == acc ) return false;

Также, если у человека может быть несколько учетных записей, недостаточно проверить условие выше. Вы должны перебрать все элементы с одинаковыми s_name и s_addr, чтобы проверить, существует ли уже учетная запись.

Я думаю, что вместо оператора if вы должны сделать следующее

while ( SPiter != SPeople.end ( ) &&
        SPiter -> s_name == name &&
        SPiter -> s_addr == addr &&
        SAiter -> s_account != acc )
{
    ++SPiter; ++SAiter;
}

if ( SPiter != SPeople.end ( ) && SPiter -> s_name == name && SPiter -> s_addr == addr )
{
   return false;
}


SPeople.insert( SPiter, personToAdd );
SAccounts.insert( SAiter, accountToAdd );

return true;
22.03.2014
Новые материалы

Кластеризация: более глубокий взгляд
Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

Как написать эффективное резюме
Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

Частный метод Python: улучшение инкапсуляции и безопасности
Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

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

Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..