2017-01-07 8 views
1

は、次のことを仮定しますため、アプリケーションがどのように機能するかに未確認の読み取り

struct C { 
    ... // lots of other stuff 
    int get(int key) const { return m.at(key); } // This will never throw 
private: 
    std::unordered_map<int, int> m; 
}; 

、私はgetスローしないことを知っています。できるだけ早くgetにしたいと思います。そこで、私はアクセスをチェックしないようにしたいと思います。すなわち、return m[key]のようなものを書いています。もちろん、私は正確にそれを書くことができませんget const。しかし、私はgetを維持したいと思います。です。

struct C { 
    ... // lots of other stuff 
    int get(int key) const { return const_cast<C *>(this)->m[key]; } 
private: 
    std::unordered_map<int, int> m; 
}; 

良い方法があります:

ここに私が思い付いただけ(醜い)ソリューションですか?

+4

なぜ 'm(key)'が 'm [key]'よりも効率が悪いと思いますか?あなたはそれらを計時しましたか?キーを見つける主な作業は同じですが、唯一の違いは、キーが見つからない場合に起こることです。 – Walter

答えて

2

私はこの質問の背後にある非常に推論に反対します。 keyが原因でエラーをキャッチすることに関連するオーバヘッド(map.at()map[])は、おそらく最初にkeyを見つけるコストと比較して、ごくわずかです。 しかし、おそらく検証/測定さえしていないような限界的な効率上の利点のために、ランタイムエラーの重大なリスクを喜んで抱いています。 keyが常にマップに含まれていることを知っていると思うかもしれませんが、将来のコード変更(他人が導入したバグを含む)によって変更される可能性はありますか?

あなたが本当に知っているならば、あなたはイテレータが無効である(map.end()にすなわち等しい)返された場合にはバグが明示的になり

map.find(key)->second; 

を使用する必要があります。あなたは、プリプロダクションコードでassertを使用することができる、すなわち(assertが空のマクロの場合)製品コードで除去し

auto it = map.find(key); 
assert(it!=map.end()); 
return it->second; 

+0

Bjarne Stroustrupの** The C++ Programming Language **(第4版)で効率が必要なときに、[]を使うようにアドバイスしました。しかし、私は今この声明を見つけることができず、彼がベクトルではなく地図について話していたことを今確信しています。私はあなたの推論に同意します。 – AlwaysLearning

3

一つのアプローチは、std::unordered_map::findを使用することです:

struct C { 
    ... // lots of other stuff 
    int get(int key) const { return m.find(key)->second; } 
private: 
    std::unordered_map<int, int> m; 
}; 
+1

これは正しい方法です。** iff ** 'key'がマップに含まれていることが保証されています。 – Walter

+0

確かに。 OPはチェックされていないアクセスを要求しましたが、キーが存在するかどうかわからない場合は、逆参照する前にイテレータを 'm.end()'と比較する必要があります。 –

関連する問題