【问题标题】:is there issue will stringstream.str().c_str()? [duplicate]stringstream.str().c_str() 会有问题吗? [复制]
【发布时间】:2014-01-10 01:53:16
【问题描述】:

代码:

stringstream ss("012345678901234567890123456789012345678901234567890123456789");  

有些文章说由于 ss.str 返回 temp 对象,后续使用是错误的,在调用 .c_str() 之前会被解构;

 const char* cstr2 = ss.str().c_str();  

但是我运行的例子,有没有问题?怎么理解?

【问题讨论】:

  • 可以链接文章吗?
  • 实际上,这是一个骗局。 [编辑:哦,不,不完全是。几乎!]
  • 如果你能解释一下你预计会出现什么样的“问题”会更好,然后我们可以告诉你为什么你没有遇到它。
  • @LightnessRacesinOrbit 为什么不应该是一个骗局? stringstream::str() 确实返回std::string(复制/对象)

标签: c++ stringstream


【解决方案1】:

但是我运行例子,没有问题吗?

其实表达式没有错:

const char* cstr2 = ss.str().c_str();

ss.str() 返回的临时(复制)对象将存在足够长的时间,让您可以使用c_str() 获取底层 c 字符串。

当然,在表达式结束时,您将有一个const char 指针,指向一个可能 被释放的对象(这在很大程度上取决于std::basic_string 的实现)。

因此,这可能不是一个好主意。你应该做的是:

auto x = ss.str();
const char* cstr2 = x.c_str(); 

上面的代码不会给您带来任何麻烦,因为str() 的返回值现在正在被复制/不再是临时值,并且对x.c_str() 的访问将为您提供一个有效的指针。

【讨论】:

  • 您的回答:“没有错。可能有问题。以下是如何让您的代码不再出错。”
  • @LightnessRacesinOrbit,我的回答“这个表达式没有问题。但是表达式的结果是一个问题:这是解决方法”。
  • 我想如果你只引用我同意的表达方式。但是你引用了整个 statement,而 statement 不好,因为它 (a) 无用且 (b) 危险 :)
  • @LightnessRacesinOrbit 这就是为什么我在“表达式没有错”中使用了“表达式”这个词。
【解决方案2】:

又一个奇妙的 C++ 地雷。

基本上,您的指针引用了一个内存块(C 字符串),该内存块引用了您进行双重处理时流中任何内容的临时副本(字符串)。

str() 返回一个临时对象。

临时对象的预期寿命相当短。要么有人立即引用他们(例如string& s = ss.str()),要么他们在他们出生的陈述结束时死去。

但是,编译器允许通过 c_str() 间接获得对同一内存块的引用,因此它在编译器的雷达下飞行。太可惜了。

所以你的指针在 c_str 得到它的时候确实是有效的,但只要你在普通的旧 C 中做这样的事情就差不多了:

const char * cstr2;
{
    char ss_str[100];            // str() return value is dynamically created
    char * c_str = &ss_str_[10]; // c_str() takes a reference to some part of it
    cstr2 = c_str;               // cstr2 takes an indirect reference to str() ret. val.
}                                // compiler pulls the plug on str() ret. val.

所以,在这个语句结束之后,c_str 已经在引用 str() 返回的任何字符串的尸体。

现在由于临时对象是在堆栈上分配的,您可能永远不会注意到这个问题。对象释放本身可能不会修改失效的字符串值,但一旦编译器重用这部分堆栈,proverbial guru 就会有一些东西需要考虑。

【讨论】:

  • 现在看来“IBM 的这一点”链接已经没用了。它会自动重定向到 IBM 知识中心,而无需参考原始页面/文章。
  • 嗯,这就是您的网络可靠性... :)
  • 你不能引用字符串,你实际上必须复制返回的对象!由于与您不能使用c_str() 的返回值完全相同的原因,该引用将在函数调用结束时变为无效。
【解决方案3】:

首先,重要的是要了解尝试使用悬空指针并不能保证以任何明显的方式失败。它可以看起来像“工作”一样频繁,因为它可以惊人地崩溃。

其次,是的,该代码无效,您不应该这样做。字符串流的生命周期并不重要,因为std::stringstream::str() 返回按值(即内部缓冲区的副本),但是你仍然会受到该字符串的影响在你可以使用它的 C 字符串指针之前作用域。

【讨论】:

  • 我认为值得指出的是,在稍微修改的上下文中,代码是合法的 MessageBox(..., const char*); MessageBox(..., stream.str().c_str());
猜你喜欢
  • 2011-05-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-14
  • 1970-01-01
  • 1970-01-01
  • 2012-01-14
  • 1970-01-01
相关资源
最近更新 更多