5

次のコード セグメントは、 BOOST_FOREACHステートメント内で無限ループに入りますが、その理由がわかりません。Boost のドキュメントからわかる限り、BOOST_FOREACHループ内で「break」を使用しても問題ありません。ここで何がうまくいかないのでしょうか?

std::vector<std::wstring> sectors = getSectors();
if (!_sectorCodes.empty()) {  // _sectorCodes is a std::set<std::wstring>.
    bool ok = false; // did we find the sector code we wanted?
    BOOST_FOREACH(Symbol sector, sectors) {
        if (_sectorCodes.find(sector) != _sectorCodes.end()) {
            ok = true;
            break;
        }
    }
    if (!ok) return NULL;
}

BOOST_FOREACHループを for ループ (イテレータ from sectors.begin()to を使用)に置き換えると、sectors.end()問題なく動作します (無限ループはありません)。

バージョンと追加情報:

  • ブースト: 1.40.0
  • gcc: 4.1.2
  • アーキテクチャ: x86_64
  • この動作はリリース ビルドでのみ発生します。デバッグ ビルドを実行すると、期待どおりに動作します。
  • Visual Studio でコンパイルすると、期待どおりに動作します。つまり、無限ループはありません。

mkb の質問に答えて、実行すると次のようになりますgcc -E

if (!_sectorCodes.empty()) {
 bool ok = false;
 if (boost::foreach_detail_::auto_any_t _foreach_col148 = boost::foreach_detail_::contain( (sectors) , (true ? 0 : boost::foreach_detail_::or_( boost::foreach_detail_::and_( boost::foreach_detail_::not_(boost::foreach_detail_::is_array_(sectors)) , (true ? 0 : boost::foreach_detail_::is_rvalue_( (true ? boost::foreach_detail_::make_probe(sectors) : (sectors)), 0))) , boost::foreach_detail_::and_( boost::foreach_detail_::not_(boost_foreach_is_noncopyable( boost::foreach_detail_::to_ptr(sectors) , boost_foreach_argument_dependent_lookup_hack_value)) , boost_foreach_is_lightweight_proxy( boost::foreach_detail_::to_ptr(sectors) , boost_foreach_argument_dependent_lookup_hack_value)))))) {} else if (boost::foreach_detail_::auto_any_t _foreach_cur148 = boost::foreach_detail_::begin( _foreach_col148 , (true ? 0 : boost::foreach_detail_::encode_type(sectors, boost::foreach_detail_::is_const_(sectors))) , (true ? 0 : boost::foreach_detail_::or_( boost::foreach_detail_::and_( boost::foreach_detail_::not_(boost::foreach_detail_::is_array_(sectors)) , (true ? 0 : boost::foreach_detail_::is_rvalue_( (true ? boost::foreach_detail_::make_probe(sectors) : (sectors)), 0))) , boost::foreach_detail_::and_( boost::foreach_detail_::not_(boost_foreach_is_noncopyable( boost::foreach_detail_::to_ptr(sectors) , boost_foreach_argument_dependent_lookup_hack_value)) , boost_foreach_is_lightweight_proxy( boost::foreach_detail_::to_ptr(sectors) , boost_foreach_argument_dependent_lookup_hack_value)))))) {} else if (boost::foreach_detail_::auto_any_t _foreach_end148 = boost::foreach_detail_::end( _foreach_col148 , (true ? 0 : boost::foreach_detail_::encode_type(sectors, boost::foreach_detail_::is_const_(sectors))) , (true ? 0 : boost::foreach_detail_::or_( boost::foreach_detail_::and_( boost::foreach_detail_::not_(boost::foreach_detail_::is_array_(sectors)) , (true ? 0 : boost::foreach_detail_::is_rvalue_( (true ? boost::foreach_detail_::make_probe(sectors) : (sectors)), 0))) , boost::foreach_detail_::and_( boost::foreach_detail_::not_(boost_foreach_is_noncopyable( boost::foreach_detail_::to_ptr(sectors) , boost_foreach_argument_dependent_lookup_hack_value)) , boost_foreach_is_lightweight_proxy( boost::foreach_detail_::to_ptr(sectors) , boost_foreach_argument_dependent_lookup_hack_value)))))) {} else for (bool _foreach_continue148 = true; _foreach_continue148 && !boost::foreach_detail_::done( _foreach_cur148 , _foreach_end148 , (true ? 0 : boost::foreach_detail_::encode_type(sectors, boost::foreach_detail_::is_const_(sectors)))); _foreach_continue148 ? boost::foreach_detail_::next( _foreach_cur148 , (true ? 0 : boost::foreach_detail_::encode_type(sectors, boost::foreach_detail_::is_const_(sectors)))) : (void)0) if (boost::foreach_detail_::set_false(_foreach_continue148)) {} else for (Symbol sector = boost::foreach_detail_::deref( _foreach_cur148 , (true ? 0 : boost::foreach_detail_::encode_type(sectors, boost::foreach_detail_::is_const_(sectors)))); !_foreach_continue148; _foreach_continue148 = true) {
  if (_sectorCodes.find(sector) != _sectorCodes.end()) {
   ok = true;
   break;
  }
 }
 if (!ok) return PatternFeatureSet_ptr();
}

この展開の注目すべき機能の 1 つは、ネストされた 2 つの for ループがあることです。内側のループと外側のループで何が起こっているのかを理解することはできませんが、(Davidが示唆しているように)内側のループだけから抜け出し、BOOST_FOREACHが一部の人にとってそれを適切に処理していない可能性はありますか理由?

4

1 に答える 1

4

私は関数を単純化することに賭けます:

std::wstring const* find(std::vector<Symbol> const& sectors) {
    if (!_sectorCodes.empty()) {
        BOOST_FOREACH(Symbol sector, sectors) {
            std::set<Symbol>::const_iterator it = _sectorCodes.find(sector);
            if (it != _sectorCodes.end()) { return &*it; }
        }
    }
    return NULL;
} // find

問題を解決します。

最適化を使用しても、知るのは難しいです...しかし、少なくともコードはより読みやすくなります。テストするgccのバージョンはありませんが、私のバージョン(またはclang)で問題が発生したことはないので、提案できるのは:xだけです。

于 2012-05-15T16:06:22.970 に答える