2016-12-08 21 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'in temeldeki dize nesnesi nasıl taşınır?Std :: ostringstream'in temeldeki dize nesnesini nasıl taşıyabilirim?

+2

Sana s = hareket 'tarafından yapabileceğini tahmin (oss.rdbuf() -> str())' [Ah, kontrol ettim, ** yapamazsın **] Ancak, kilidin varsayımlarını, ayağın altından halıyı çekerek riske atabilirsiniz. Bunu neden istiyorsun? –

+1

Sanırım C++ 17'den "node handle" kullanarak ilginç bir şey icat edebilirsiniz: http://en.cppreference.com/w/cpp/container/node_handle – alexeykuzmin0

+4

Bu mümkün değil, 'std ' :: basic_stringbuf', temelindeki arabellek olarak bir std :: basic_string işlevini kullanır (uygulamada bu şekilde yapılsa bile). – user657267

cevap

3

Standart, std::ostringstream::str() returns a copy'un diyor.

Bu kopyadan sakınmanın bir yolu, dize arabelleğini doğrudan açığa çıkaran başka bir std::streambuf türetilmiş sınıf uygulamaktır. Boost.IOStreams bu oldukça önemsiz kılan:

#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

Bu * dizgeyi * kopyalar, çünkü '' buffer-> string'' ne bir prelüde ne de geçicitir, ne de otomatik depolama süresinin uçucu olmayan bir nesnenin isminin kopyasını almak için gereklilikleri karşılamaz. (ve aynı tipte). Bu durumda, örneğin * ile bir hareketi zorlamak için * seçeneğiniz vardır. '' Std :: move''. 'Buffer-> string'' her halükarda kopya elemenasyonu için uygun olamayacağı için, diğer optimizasyonları engellemez. –

+0

@ArneVogel Burada başka bir kopyalama işlemi olduğu doğru. Güncellenmiş. –

İlgili konular