【问题标题】:Assigning a std::string's c_str() result to that same std::string guaranteed safe by the standard?将 std::string 的 c_str() 结果分配给标准保证安全的同一 std::string?
【发布时间】:2021-10-12 08:48:53
【问题描述】:

关于std::string,以下代码是否被标准保证安全?

#include <string>
#include <cstdio>

int main() 
{
    std::string strCool = "My cool string!";
    const char *pszCool = strCool.c_str();
    strCool = pszCool;
    printf( "Result: %s", strCool.c_str() );
}

我看到的声明表明 c_str 的结果只能保证安全使用,直到对同一 std::string 进行另一个方法调用,但我不清楚传递 const char * 是否安全是否返回分配方法。

使用实际编译器(最新版本的 GCC、Clang 和 MSVC)进行测试时,它们似乎都支持这种行为。

此外,编译器还支持将字符串的后缀分配回自身,例如strCool = pszCool + 3 在这个例子中;结果将是该字符串与传入的字符串具有相同的值。

这种行为是否以某种方式得到保证,或者我只是幸运的是我测试过的编译器提供的标准库支持这种情况?

【问题讨论】:

  • 嗨!你标记了这个问题stl,但看起来你正在使用 C++ 标准库。你用的是哪个库?另请参阅 What's the difference between "STL" and "C++ Standard Library"?stl 说明。
  • 听起来你没有“测试”过任何东西。您只是保存了指向 C 字符串的指针,并验证没有发生崩溃。看here:The c_str() result becomes invalid if the std::string is destroyed or if a non-const member function of the string is called. So, usually you will want to make a copy of it if you need to keep it around. 换句话说,a) 确保原始 std::string 保持不变,和/或 b) strcpy() 到另一个缓冲区。
  • 抛开标准中的任何一点点:我希望典型的 C++ 库实现要么在删除旧缓冲区之前分配一个新的内部缓冲区,要么在新字符串适合的情况下重用相同的缓冲区。如果 C++ 标准要求任何一种行为,我会感到惊讶,因此默认情况下,这变得未指定。如果实现选择重用缓冲区,这将成为重叠副本,这是未定义的行为。这就是我的理由。
  • @paulsm4 我通过在调试器中单步执行代码并识别例如如上所述的 memmove 操作,这并不能很好地转化为 StackOverflow 问题,尽管我本可以承认这一点。
  • @Brian 谢谢,我的意思是用 STD 来标记它,这已经有用地修复了 :)

标签: c++ language-lawyer std


【解决方案1】:

在 C++17 中,这被指定为:

basic_string&amp; operator=(const charT* s);

返回: *this = basic_string(s).

备注:使用traits::length()

这一系列操作保证在原始存储被破坏之前制作副本。虽然标准库不需要使用这个精确的操作序列来实现这个调用,但它需要具有与描述的相同的行为。

在 C++20 中,这个措辞被修改了,但如果改变了意思,我会感到惊讶。

【讨论】:

  • 这建议了另一种分配形式,即使标准发生变化,也始终保证有效:strCool = std::move(std::string(pszCool));
  • 是的,这会起作用,但我的意思是它已经保证起作用了。
猜你喜欢
  • 2022-10-27
  • 2023-01-11
  • 2012-06-02
  • 2016-03-11
  • 2020-11-04
  • 2011-09-21
  • 1970-01-01
相关资源
最近更新 更多