【问题标题】:How to move std::ostringstream's underlying string object?如何移动 std::ostringstream 的底层字符串对象?
【发布时间】:2017-04-23 10:42:42
【问题描述】:
#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的底层字符串对象?

【问题讨论】:

  • 我猜你可以通过s = move( oss.rdbuf()-&gt;str() ) [哦,我检查过,你不能],但是你有可能通过拉动来打破流代码的假设地毯从它的脚下。*。你为什么要这个?
  • 我认为你可以使用 C++17 中的node handle 发明一些有趣的东西:en.cppreference.com/w/cpp/container/node_handle
  • 这是不可能的,std::basic_stringbuf 没有义务使用std::basic_string 作为其底层缓冲区(即使这是实践中的做法)。
  • @user657267:它 确实 似乎有一个字符串作为缓冲区,这就是 str member functions 的全部意义所在。但它不提供对它的可变访问。嗯。
  • 我知道两种使用basic_string 的实现和一种使用普通char 数组的实现。

标签: c++ performance c++11 move-semantics rvalue-reference


【解决方案1】:

标准说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';
}

【讨论】:

  • 这个copy这个字符串也是,因为buffer-&gt;string既不是prvalue,也不是临时的,也不符合复制省略作为非名字的要求- 自动存储持续时间的易失性对象(并且与返回的类型相同)。在这种情况下,您必须使用例如强制移动std::move。由于buffer-&gt;string 在任何情况下都不可能有资格进行复制省略,因此这不会妨碍其他优化。
  • @ArneVogel 你说得对,这里还有另一个复制操作。已更新。
猜你喜欢
  • 2014-12-03
  • 2014-08-30
  • 2020-09-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-30
相关资源
最近更新 更多