2016-12-08 4 views
8
#include <sstream> 
#include <string> 

using namespace std; 

template<typename T> 
string ToString(const T& obj) 
{ 
    ostringstream oss; 
    oss << obj; 

    // 
    // oss will never be used again, so I should 
    // MOVE its underlying string. 
    // 
    // However, below will COPY, rather than MOVE, 
    // oss' underlying string object! 
    // 
    return oss.str(); 
} 

std :: ostringstreamの基になる文字列オブジェクトを移動するにはどうすればよいですか?std :: ostringstreamの基になる文字列オブジェクトを移動するには?

+2

私はあなたが' S =移動(> STR()oss.rdbuf())でそれを行うことができると思います**]しかし、敷物を足元から引っ張ってストリームコードの前提を壊す危険があります。なぜこれが欲しいのですか? –

+1

私はあなたがC++の 'node handle'を使って興味深いものを作り出せると思います。http://en.cppreference.com/w/cpp/container/node_handle – alexeykuzmin0

+4

これは不可能です。' std :: basic_stringbuf'は、基礎となるバッファとして 'std :: basic_string'を使います(これは実際のところですが)。 – user657267

答えて

3

標準ではstd::ostringstream::str() returns a copyとなっています。

このコピーを回避する1つの方法は、文字列バッファを直接公開する別のstd::streambuf派生クラスを実装することです。 Boost.IOStreamsが、これは非常に簡単になり: - [ああ、私はあなたがすることはできません、確認** `

#include <boost/iostreams/stream_buffer.hpp> 
#include <iostream> 
#include <string> 

namespace io = boost::iostreams; 

struct StringSink 
{ 
    std::string string; 

    using char_type = char; 
    using category = io::sink_tag; 

    std::streamsize write(char const* s, std::streamsize n) { 
     string.append(s, n); 
     return n; 
    } 
}; 

template<typename T> 
std::string ToString(T const& obj) { 
    io::stream_buffer<StringSink> buffer{{}}; 

    std::ostream stream(&buffer); 
    stream << obj; 
    stream.flush(); 

    return std::move(buffer->string); // <--- Access the string buffer directly here and move it. 
} 

int main() { 
    std::cout << ToString(3.14) << '\n'; 
} 
+2

'' buffer-> string''もprvalueでも一時的でもなく、また自動保存期間の不揮発性オブジェクトの名前であるコピーelisionの要件を満たしていないので、 (返されるのと同じ型の)。この場合、例えば*を使用して移動を強制する必要があります。 '' std :: move''です。いずれの場合でも '' buffer-> string''はコピーエリミッションには適さない可能性があるので、他の最適化を妨げるものではありません。 –

+0

@ArneVogelここに別のコピー操作があります。更新しました。 –

関連する問題