【问题标题】:stringstream::str copy lifetimestringstream::str 复制生命周期
【发布时间】:2014-02-03 18:19:24
【问题描述】:

很多 C++ 程序员在第一次使用 stringstreams 时会忽略(阅读:我)的事实是,stringstream::str() 返回的副本是临时的,它会持续到使用它的表达式的结尾。但是,我不明白:

  1. 这是如何完成的。查看 libstdc++ 的 sstream 标头,我只看到制作并返回了一个副本。寿命如何限制?
  2. 为什么这是期望的行为,尤其是因为这是一个常见的问题。如果仍然在制作副本,为什么我不能拥有它?

请注意,这不是 stringstream, string, and char* conversion confusion 的副本。以上解释了行为和解决方法;我正在寻找机制和基本原理。

【问题讨论】:

  • 我不确定你在问什么。 stringstream::str 返回内部字符串的副本,除非我遗漏了什么。
  • 这个问题存在于任何返回可以访问数据指针的东西的副本的东西。碰巧从std::stringstreamconst char * 发生的频率比其他情况要高。无论如何,您说另一个答案解释了行为,但您需要机制。我不太确定如何区分它们。
  • @dauphic 我想我误解了复制的内容 - 你是说 string 对象被复制得很浅,所以它指向的字符数组是共享的?
  • @roysc:AlexTelishev 的回答解释了这一点。它返回内部字符串的完整副本,在销毁之前有效,但c_str()的返回值只在表达式结束之前有效。
  • 我有点困惑,为什么这么多答案都在谈论c_str(),我在你的问题中没有看到任何地方提到这一点?他们所说的这个表达是什么? stringstream.str().c_str()?这个问题是关于str() 还是c_str()?听起来主要是关于c_str()

标签: c++ memory stringstream


【解决方案1】:

这不是stringstream 的问题。这是c_str 函数的问题——它返回指向std::stringchar* 表示的指针,但它只存在于原始字符串的生命周期内。当您致电char *str = ss.str().c_str() 时,实际上会发生以下情况:

string tmp = ss.str();
char *str = tmp.c_str();
tmp.~string (); // after that line the pointer `str` is no longer valid

c_str 是仅出于兼容性和速度目的而提供的危险函数,您应该避免使用它。

【讨论】:

  • 我误解了str 引用,并认为返回的对象有些“特殊”。这现在看起来很明显了。
【解决方案2】:

stringstream::str() 返回一个string。时期。它是按价值来做的,所以你可以用它做任何你想做的事情(例如,当然拥有所有权)。

【讨论】:

  • 这是一个临时值。你甚至无法获取它的地址。如果你想在表达式结束后使用它,你必须复制它,整个东西。
【解决方案3】:

这是怎么做到的?查看 libstdc++ 的 sstream 标头,我只看到制作并返回了一个副本。寿命如何限制?

str() 按值返回,这意味着它返回的对象在完整表达式结束时被销毁。这只是临时工的工作方式。

为什么这是期望的行为,尤其是因为它是一个常见的问题。如果无论如何都在制作副本,为什么我不能拥有它?

这是对传统 IOStreams 的修正。不推荐使用的旧流类strstream 有一个str() 方法,该方法返回指向其内部缓冲区的指针。为了防止指针失效,必须“冻结”流,这意味着无法调整缓冲区大小。

标准 IOStreams 将缓冲区的副本作为 std::basic_string<charT> 对象返回,因此不再需要冻结流。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-21
    相关资源
    最近更新 更多