文字列クラスの効率
今、C++ で文字列を表すクラスを書いているんだけど、とりあえずインターフェースとして C# の String クラスを真似してたりする。
そこで気付いたんだけれど、例えば、C# の IndexOf は複数の定義があって、その中に、
public int IndexOf( String value ); public int IndexOf( String value , int startIndex ); public int IndexOf( String value , int startIndex , int count );
こういう定義があったりする。
この時、IndexOf( String , int , int ) さえ実装しておけば、
int IndexOf( String value ){ return IndexOf( value , 0 ); } int IndexOf( String value , int startIndex ){ return IndexOf( value , startIndex , Length() - startIndex ); }
これでいいと思うかもしれないけれども、効率を考えた場合、これはあまり良くない。
なぜかというと、IndexOf( String , int , int ) は次のように定義されているからだ。
int IndexOf( String value , int startIndex , int count ){ if( value == null ){ throw ぬるぽ } if( count < 0 || startIndex < 0 || startIndex + count > Length() ){ throw 引数不正 } // あとは通常の処理 }
IndexOf( String , int ) から IndexOf( String , int , int ) を呼び出した場合、startIndex が負の値でなくて Length() を超えていないことが分かれば count が負の値にならず、startIndex + count が Length() を超えないことは分かる。count のチェックは無駄だ。
そして、IndexOf( String ) から IndexOf( String , int ) を呼び出した場合は、startIndex をチェックする必要すらない。
つまり、無駄なエラー処理を行っているのだ。
なので、以下のようにしてやるのがいいと思う。
int IndexOf( String value ){ if( value == null ){ throw ぬるぽ } return _IndexOf( value , 0 , value.Length() ); } int IndexOf( String value , int startIndex ){ if( value == null ){ throw ぬるぽ } if( startIndex < 0 || startIndex > Length() ){ throw 引数不正 } return _IndexOf( value , startIndex , Length() - startIndex ); } int IndexOf( String value , int startIndex , int count ){ if( value == null ){ throw ぬるぽ } if( count < 0 || startIndex < 0 || startIndex + count > Length() ){ throw 引数不正 } return _IndexOf( value , startIndex , count ); } int _IndexOf( String value , int startIndex , int count ){ // エラーはないものとして処理を行う }
まあ、そうは言ってもこの程度なら無視出来るオーダーだろうし、そんな気にしなくて良いのかもしれない。
けれども、この無駄に気付く人と気付かない人とでは、かなりの差があるような気がする。