【问题标题】:What does c_str() method from string class returns?字符串类的 c_str() 方法返回什么?
【发布时间】:2013-07-01 11:05:44
【问题描述】:

我想访问由字符串类维护的数组的起始地址。

string str="hey";
char* pointer=(char*)str.c_str();
  1. 指针是否指向数组的地址(由字符串类维护)?还是字符串类将从动态内存中创建一个新数组并将现有字符串复制到其中并返回它的地址?

  2. 如果这不是正确的方法,那么如何访问字符串类维护的数组的起始地址?

【问题讨论】:

  • 为什么你想要这个地址?你想对字符串做什么?
  • 您在寻找 C++11 答案还是 C++03 答案?正确答案取决于此。如果没有进一步的说明,我会进一步假设 C++11。
  • 也许您可以回答问题,以便我们更好地回答您的问题?你几分钟前就来过这里。
  • @trojanfoe 实际上我需要找到一个数据包的 crc。计算它的函数是用c编写的。它需要数据包的起始地址。我正在使用字符串对象作为数据包。所以我需要它的起始地址,以便我可以将它传递给该函数并完成我的工作。
  • @phresnel 先生,我真的很抱歉。我什至不知道我正在使用什么版本。我只是在工作。是否有任何 API 或实用程序可以告诉我当前版本,以便我也可以告诉你。 :)

标签: c++


【解决方案1】:

C++11 标准中明确规定.c_str()(以及更新的.data())应返回指向std::string 使用的内部缓冲区的指针。

通过.c_str() 获得指针后对std::string 的任何修改可能 导致所述char * 返回变为无效(即 - 如果std::string 在内部必须重新分配空间)。

在以前的 C++ 标准中,允许返回任何东西。但作为标准不要求用户解除分配结果,我从未见过任何实现返回任何新分配的内容。至少 GNU gcc 和 MSVC++ 的 STL 字符串是内部以零结尾的字符数组,由c_str() 返回。

因此可以安全地假设(通常对 C++ 谨慎)在任何 C++ 版本中的任何实现 .c_str() 将返回内部缓冲区。

换句话说 - 你永远不应该保留 .c_str() 的值,除非你 100% 确定它在未来的任何时候都不会改变它的大小(除非它是 const,也就是说)。

附:顺便说一句,你永远不应该这样做char* pointer=(char*)str.c_str();。它是const char *,你不应该修改内容,部分原因是上面的 - 你可能最终会覆盖一些其他对象的内存破坏std::string的内部状态,以防实现做一些花哨的事情,例如为更快的.find() 索引字符(新人看到,但是嘿 - 这是一个封装!)

【讨论】:

  • 这正是我所期待的答案。
  • ... 当然,修改一个 常量字符串 几乎肯定会遇到可怕的情况,因为它存在于进程中的位置(即可能在只读内存页面上)。
  • @Andrian Nord 如果调整大小的概率为 0,那么?我创建了一个新的字符串对象并使用了 resize(512) 方法。 512 是我的应用程序中可能的最大字符串长度。现在如果我使用 c_str() 获取地址,然后在对象上使用 append() 方法,可以吗?
  • 至少在 当前 GNU 和 Microsoft STL 实现中(并且可能在任何其他非疯狂的实现中)都可以。但是标准本身说指针可能被任何字符串修改无效,所以从技术上讲,如果你想编写 RightThing(tm),你可能不应该使用这种技术。如果您想 100% 确定,您可能应该编写自己的固定大小的字符串实现,或者找到一些已经存在的实现。 STL 的设计不是固定大小的,因此在您使用的当前或任何未来版本的 STL 实现中,您的许多假设都可能被证明是错误的。
  • 复制那个..一遍又一遍..:)
【解决方案2】:

注意:我的回答只对 pre-C++11 正确。对于 C++11,this 是正确答案。


  1. 它返回一个以空结尾的 C 字符串。 std::string 本身不是以空值结尾的,因此允许(并且可能会)返回一个新分配的 const char 数组。如果创建的std::string 超出范围或发生变异,则返回的c_str() 字符串无效。

  2. data() 返回数据,但请注意它不是以 null 结尾的字符串。

在这两种情况下,您都应该调整该数据,data()c_str() 都返回指向 const char 的指针,而您真的不应该。

例如,std::strings 被允许作为引用计数字符串(尽管这不再常见),甚至可以在其数据上使用时髦的索引方案(但从未见过)。

【讨论】:

    【解决方案3】:

    你可以通过char *address = &str[0];获取字符串的起始地址。无需将字符串转换为 c 字符串表示形式。

    【讨论】:

    • @PeterWood 不,不需要。
    • @davmac 我已经用过很多次了。你能给出一些理由吗,因为我想不出任何理由。
    • @Aman Deep Gautam:因为标准没有强制要求。在许多实现中,它可能有效,或者看起来有效,但我不认为它可以保证这样做。
    • @davmac 我认为它确实符合当前标准。
    • @AmanDeepGautam:“我已经用过很多次”在 C++ 中从来都不是一个有效的论点,因为它有大量的实现和未定义的行为。
    【解决方案4】:

    如果您确实想要字符串中的“数据”,那么string::data() 就是您要查找的函数。

    但是请注意,与c_str() 一样,它是指向数据的const 指针——您不应该修改此数据。

    【讨论】:

      【解决方案5】:

      在 C++11 中,返回的指针指向字符串对象当前用来存储符合其值的字符的内部数组。

      详情请参阅http://www.cplusplus.com/reference/string/string/c_str/

      【讨论】:

      • @trojanfoe 我在答案中发布的链接说:“string::data 和 string::c_str 都是同义词,返回相同的值。”,你的意思是它错了吗?
      • @trojanfoe C++11 中的情况可能有所不同。至少stackoverflow.com/a/7554172/533480是这么说的。
      • 同意;删除我的commnets。
      猜你喜欢
      • 1970-01-01
      • 2018-08-23
      • 2021-04-02
      • 2015-09-04
      • 2013-03-10
      • 2021-11-06
      • 1970-01-01
      相关资源
      最近更新 更多