2016-02-08 2 views
0

Я новичок в shared_ptr от boost и рассматриваю возможность перебора моего набора, чтобы получить лучший объект. EDIT: добавлена ​​информация о first_worldсбой общего утверждения указателя после итерации в цикле

std::set<World::CPtr> first_world = ... // long call, but it gets a set of constant shared pointers to the class World, where various methods exist 

    typedef boost::shared_ptr<World const> CPtr; 
    World::CPtr best = *(first_world.begin()); 
    for (World::CPtr lo : first_world) { 
    if (best->getValue() >= lo->getValue()){ 
     best = lo; 
    } 
    } 

Позже я хочу использовать этот общий указатель, Моя программа вылетает с сообщаться это утверждение `точек = 0' не удалось!. Я следовал правилам от here, я имею в виду, что я использовал общий указатель как итератор в цикле, но затем назначаю его другому указателю. Это плохая практика, есть ли лучшая практика?

cout << "name is: " << best->getDefinition() << endl; 
+0

Почему вы используете 'boost :: shared_ptr', когда вы, очевидно, используете C++ 11? – molbdnilo

+0

@molbdnilo Почему бы и нет? Кажется, не имеет значения. В прошлый раз, когда я проверял типы, не то же самое, и имеет смысл использовать тот тип, который требуется вашей кодовой базе ... – sehe

+0

ну C++ 11 не нужно, я бы изменил его на более старый стандарт - что я хочу понять почему это не работает, как заставить его работать. – beginh

ответ

0

Ничто не вопиюще неправильно в то, что вставил там, так что, вероятно, будет ошибка в долгосрочном вызове, который создает набор.

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

std::set<World::CPtr> first_world; 

World* pWorld = new World(); 

// Bad: 
first_world.insert(World::CPtr(pWorld)); 
first_world.insert(World::CPtr(pWorld)); 

// Oops!! You now have two independently refcounted entries in first_world! 

// emplace is just as deadly, but more subtle. 
// Now you'll have three shared pointers in your set: 
first_world.emplace(pWorld); 

Если вы смотрите через ваши записи в first_world и увидеть дубликаты, то вы будете знать, что вы в беде , Чтобы избежать таких ошибок, убедитесь, что вы только создаете shared_ptrs из других shared_ptrs (или boost::make_shared).

Так вот кончик # 1: Избегайте конструирования shared_ptrs от необработанных указателей. (Это включает в себя указатель this, если миры добавляют себя к вашему набору ... если вы это делаете, лучше начинайте поиски по Google enable_shared_from_this).

Теперь давайте проследим, что руководство, чтобы получить ожидаемое поведение:

std::set<World::CPtr> first_world; 

World::CPtr spWorld1 = boost::make_shared<World>(); 
World::CPtr spWorld2{spWorld1}; 

first_world.insert(spWorld1); 
first_world.insert(spWorld2); 
// Just one element in first_world now, as expected. 

Наконец, несколько (несколько не связанных между собой) предложения:

  • std::set, как вы объявили его смотрит только на адрес объектов World в куче, когда он сравнивает записи. Поэтому, если у вас есть два разных мира в куче, которые логически идентичны, то они оба будут иметь разные записи в наборе. Это ваше намерение? Вам нужно будет подключить собственную функцию сравнения (второй аргумент шаблона std :: set), чтобы выполнить глубокое сравнение миров, если вы хотите избежать логических дубликатов.
  • Убедитесь, что first_world не пуст перед поиском максимального значения, в противном случае произойдут плохие вещи.
  • Стандартные алгоритмы - ваш друг! Рассмотрите возможность использования алгоритма std::max_element вместо необработанного цикла. (Это облегчает для других людей рассуждать о том, что вы делаете, с быстрым взглядом).
Смежные вопросы