new/deleteのコストは目をつぶろうか

STATUS: 故障中

void SomeStringFunc( CString &str );

 C++でこういう関数に、CStringクラス(MFCの文字列クラス)のインスタンスの参照を渡したい。
 そのとき数値を文字列に変換して渡したい。
 そういうとき数値→文字列関数を作るとすると

【案1】
1: CString& NumToStr( int n , CString &strDst ) {
2:  strDst.Format("%d",n );
3:  return strDst;
4: }

5: CString str;
6: NumToStr( 123 , str );
7: SomeStringFunc( str );

 普通こんな感じで書くことになると思うけど、わざわざテンポラリ用にインスタンス「str」を定義しないといけないのがめんどくさい。
 この例では、オブジェクトの生成は、5行目の1回だけ。同じような処理が続くときに使いまわせば、お得。

【案2】
1: CString NumToStr( int n ) {
2:  CString strResult;
3:  strResult.Format("%d",n );
4:  return strResult;
5: }

6: CString str;
7: str = NumToStr( 123 ) ;
8: SomeStringFunc( str );

 案1は、NumToStrの戻り値を受けるインスタンスを渡さないとけいないので、かっこ悪いしめんどくさい。
 あと、案3みたいに直接、ほかの関数の引数に出来ない。
 で、案2みたいにしてみる。
 でも、オブジェクト生成・削除の回数が多い。

(1) 6秒目でstr生成
(2) 2行目でstrResult生成
(3) 4行目でテンポラリのインスタンス生成(以下temp)、コピーコンストラクタでstrResultの内容コピー
(4) NumToStr関数を抜けた時点でstrResult消滅
(5) 7行目でstrにtempの内容が代入(Operator =)
(6) temp消去
(7) 8行目の関数呼び出しは参照私なので生成・消滅は行われない

 オブジェクトの生成が3回。コピーが2回。

# コピー自体は、CStringが遅延コピーとか内部でやっているので、そんなにコストはかからないはず(?)

【案3】
1: CString NumToStr( int n ) {
2:  CString strResult;
3:  strResult.Format("%d",n );
4:  return strResult;
5: }

6: SomeStringFunc( NumToStr( 123 ) );

 これは楽ちん。
 でも、オブジェクト生成・削除の回数が多い。

(1) 2行目でstrResult生成
(2) 4行目でテンポラリのインスタンス生成(以下temp)、コピーコンストラクタでstrResultの内容コピー
(3) NumToStr関数を抜けた時点でstrResult消去
(4) 6行目の関数呼び出しは参照渡し(temp)なので生成・消滅は行われない
(5) SomeStringFuncから戻った時点でtemp消滅

 オブジェクトの生成が2回。コピーが1回。

【案4】
1: CString& NumToStr( int n ) {
2:  static CString strResult;
3:  strResult.Format("%d",n );
4:  return strResult;
5: }

6: SomeStringFunc( NumToStr( 123 ) );

 シングルスレッドならこれもありか。
 最初の呼び出し時のみ、2行目でインスタンス生成が行われる。

 いつもは案2,3のような形で書いてます。
 シングルスレッドのときは、案4でも書いてます。が、パラメータに2つ以上使ったり、呼び出した関数の中でもコレをつかってたりするとまずいですね。こういう使い方は危険か。

 こんな感じでいいんでしょうか。間違いとかありましたらご指摘ください。

コメント