将std::string的c_str()结果分配给同一std::string是否有标准保证安全?

3

以下代码是否符合标准,就 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++ 标准库。你使用的是哪个库?另请参阅 “STL” 和 “C++ 标准库” 有什么区别?stl 描述。 - Brian61354270
1
听起来你好像没有“测试”任何东西。你只是保存了一个指向C字符串的指针,并验证了没有发生崩溃。请看这里如果std::string被销毁或者调用了字符串的非const成员函数,c_str()的结果将变得无效。因此,通常情况下,如果需要保留它,则需要复制它。换句话说,a)确保原始的std::string保持不变,和/或b)使用strcpy()复制到另一个缓冲区。 - paulsm4
3
不考虑标准中的任何细节:我期望一个典型的C++库实现在删除旧缓冲区之前要么分配一个新的内部缓冲区,要么重复使用同一缓冲区(如果新字符串适合的话)。我会感到惊讶如果C++标准规定了任何一种行为,因此默认情况下这是未指定的。如果实现选择重复使用缓冲区,则会导致重叠复制,这是未定义的行为。这就是我的推理。 - Sam Varshavchik
@paulsm4 我通过调试器逐步执行代码并识别例如memmove操作等进行了测试,但这在StackOverflow问题中不太好转化,尽管我可以承认这一点。 - Daniel Jennings
@Brian 谢谢,我的意思是要标记为STD,这已经得到了有益的修正 :) - Daniel Jennings
1个回答

5

在C++17中,该函数被指定为:

basic_string& operator=(const charT* s);

返回:*this = basic_string(s)

备注:使用traits::length()

这些操作的顺序保证了在原始存储被销毁之前进行复制。虽然标准库不要求使用这个完全相同的顺序来实现此调用,但要求具有与描述相同的行为。

在C++20中,该措辞已经重新修订,但我会惊讶地发现意义已经改变。


1
这表明了一种替代形式的赋值,它始终保证可用,即使标准发生变化:strCool = std::move(std::string(pszCool)); - Mark Ransom
是的,那样做可以,但我的观点是它已经保证可以工作。 - Marshall Clow

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接