2016-12-08 15 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

मुझे लगता है कि आप एस = चाल 'द्वारा यह कर सकता है (oss.rdbuf() -> str())' [ओह, मैं जाँच की, ** आप नहीं कर सकते **], लेकिन आप अपने पैरों के नीचे से गली खींचकर स्ट्रीम कोड की धारणाओं को तोड़ने का जोखिम उठाते हैं। *। आप यह क्यों चाहते हैं? –

+1

मुझे लगता है कि आप 'नोड handle' से सी ++ 17 का उपयोग कर कुछ दिलचस्प आविष्कार कर सकते हैं: http://en.cppreference.com/w/cpp/container/node_handle – alexeykuzmin0

+4

यह संभव नहीं है, वहाँ कोई दायित्व नहीं है कि एक' एसटीडी :: basic_stringbuf' इसके अंतर्निहित बफर के रूप में 'std :: basic_string' का उपयोग करता है (भले ही यह अभ्यास में किया गया हो)। – user657267

उत्तर

3

मानक का कहना है कि std::ostringstream::str() returns a copy

एक तरीका यह नकल से बचने के लिए एक और 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

यह * कॉपी * स्ट्रिंग भी है, क्योंकि '' बफर-> स्ट्रिंग' 'न तो एक प्रकोप है, न ही अस्थायी है, और न ही स्वचालित संग्रहण अवधि की गैर-अस्थिर वस्तु का नाम होने की प्रतिलिपि बनाने के लिए आवश्यकताओं को पूरा करता है (और लौटने के समान प्रकार के)। इस मामले में, आपके पास * का उपयोग करके एक चाल को मजबूर करना है '' Std :: move''। चूंकि 'बफर-> स्ट्रिंग' संभवतः किसी भी मामले में प्रतिलिपि बनाने के लिए योग्य नहीं हो सकता है, यह अन्य अनुकूलन को रोकता नहीं है। –

+0

@AneneVogel आप सही हैं कि यहां एक और प्रतिलिपि है। अपडेट किया गया। –

संबंधित मुद्दे