5

戻り値の最適化に加えて右辺値参照の出現により、このようなコア関数を実装する最も効率的な方法は何でしょうか? この実装を改善するにはどうすればよいですか、それともそのままにしておくべきですか?

template <typename T>
string
to_string(const T& t)
{ 
  stringstream ss;
  ss << t;  
  return ss.str();
} 

明らかに、可能であれば、メモリのコピーまたは割り当てを避けたいと考えています。ティア。

編集:その詳細な回答については、D.ロドリゲスに感謝します。さて、私の質問の 2 番目の部分があります。これを改善する方法はありますか?

#define to_cstr( T ) (to_string( T ).c_str())

もちろん、できれば MACRO は避けたいのですが、上記のテンプレート コードをコピー アンド ペーストして ss.str().c_str() と const char* を返すと、一時的なものは十分長くは生きられません。コードは実行されているように見えますが、valgrind は文句を言います (赤信号)。

上記の to_cstr() の MACRO よりもクリーンなソリューションを思いつくことができませんでした。改善する方法はありますか、それとも放っておくべきですか?

  • ケン
4

2 に答える 2

7

放っておくだけで、そのままでも効率的です。C++03 コンパイラを使用しても、コンパイラはコピーを最適化します。

基本的に、コンパイラは、 の呼び出しコード内のオブジェクト、to_stringの return ステートメントto_string、および の return ステートメントがss.str()すべて、まったく同じメモリ位置を取るようにします。これは、コピーがないことを意味します。

標準の義務の範囲外で、私が知っているすべての 32/64 コンパイラ (VS、gcc、intel、suncc を含む) のレジスタに収まらないオブジェクトを値で返す関数の return ステートメントの呼び出し規約は合格します。関数が返されたオブジェクトを構築するメモリ内の場所へのポインター。これにより、コードは次の行の何かに内部的に変換されます。

// Not valid C++! Just for illustration purposes
template <typename T>
to_string( uninitialized<string>* res, const T& t ) {
   stringstream ss;
   ss << t;
   stringstream::str( res, &ss ); // first argument is return location
                                  // second argument is `this`
}
于 2011-10-03T13:07:42.927 に答える
0

さて、私の質問の 2 番目の部分があります。これを改善する方法はありますか?

#define to_cstr( T ) (to_string( T ).c_str())

もちろん、できれば MACRO は避けたいのですが、上記のテンプレート コードをコピー アンド ペーストして ss.str().c_str() と const char* を返すと、一時的なものは十分長くは生きられません。コードは実行されているように見えますが、valgrind は文句を言います (赤信号)。

一時的な有効期間が、一時的な値が作成される式の有効期間に対応するように、コンパイラに呼び出し元のスコープに一時的な値を作成させることができます。方法は次のとおりです。

struct TmpStr {
    mutable std::string s;
};

template<typename T>
char const* to_cstr(T value, TmpStr const& tmp = TmpStr()) {
    tmp.s = to_string(value); // your original function
    return tmp.s.c_str(); // tmp lives in the scope of the caller
}

int main() {
    printf("%s\n", to_cstr(1));
}
于 2011-10-03T14:18:59.283 に答える