2016-12-08 68 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 =舉動做(oss.rdbuf() - > STR())'[哦,我查了一下,**你不能**],但是冒險通過從地面下拉地毯來破壞流代碼的假設。你爲什麼要這樣? –

+1

我認爲你可以發明一些有趣的東西,使用來自C++ 17的'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

避免此副本的一種方法是實現另一個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也不是一個臨時的,它也不符合copy elision作爲自動存儲持續時間的非易失性對象名稱的要求(和返回的相同類型)。在這種情況下,您*有*強制移動使用例如''的std :: move''。由於''buffer-> string''在任何情況下都不可能符合副本的要求,所以這並不妨礙其他優化。 –

+0

@ArneVogel你說得對,這裏有另一個複製操作。更新。 –

相關問題