为什么std :: string没有提供对char*的隐式转换?

Dus*_*etz 26 c++ string stl

std::string提供const char*c_str()const:

获取C字符串等效项

生成以字符串对象为内容的以null结尾的字符序列(c-string),并将其作为指向字符数组的指针返回.

将自动附加终止空字符.

返回的数组指向一个内部位置,该位置具有此字符序列所需的存储空间及其终止的空字符,但此数组中的值不应在程序中修改,只有在下次调用时才会保持不变.字符串对象的非常量成员函数.

他们为什么不定义operator const char*() const {return c_str();}

use*_*116 22

从C++编程语言20.3.7(强调我的):

转换为C风格的字符串可能是由运算符const char*()而不是c_str()提供的.在这种转换出乎意料的情况下,这将提供隐式转换的便利,但会以惊喜为代价.

  • 这是一个过载的问题."char*"的行为不像任何明智的人所期望的那样,并且将"string_1 - string_2"或"string_1 - 2"这样的表达式标记为编译器错误而不是编译为无意义是有用的. (10认同)
  • 1.当转换为C字符串导致内存重新分配时,因为std :: string不一定存储NULL终止符2.当std :: string超出范围并且你留下一个悬空指针释放内存 (7认同)
  • 注意解释什么是昂贵的惊喜? (3认同)
  • 我认为简短的答案是解决重载问题.另外std :: string可以保存\ 0字符,这并不意味着std :: string的结尾. (3认同)

小智 16

我看到隐式转换至少有两个问题:

  • 即使是c_str()提供的显式转换也足够危险.我已经看到很多情况下指针存储在原始字符串对象的生命周期结束后使用(或者对象被修改从而使指针无效).通过明确打电话给c_str()你,希望能够意识到这些问题.但是通过隐式转换,很容易导致未定义的行为,如:

    const char *filename = string("/tmp/") + name;
    ofstream tmpfile(filename); // UB
    Run Code Online (Sandbox Code Playgroud)
  • 转换也会在某些情况下发生,在这种情况下,您不会期望它,并且至少可以说语义令人惊讶:

    string name;
    if (name) // always true
     ;
    name-2; // pointer arithmetic + UB
    这些可以通过某种方式避免,但为什么要首先陷入这个麻烦?

  • +1用于提供具体示例.任何人都可以说"哦,这很危险",但没有例子,很难理解如何. (7认同)
  • 这不是一个很好的例子,人们现在尝试编写像第一个示例一样的代码,遇到编译器错误,并将“.c_str()”标记到“string(...)”调用的末尾,并最终出现在同样的情况。 (2认同)

jal*_*alf 5

因为隐式转换几乎永远不会按照您的预期运行。它们可以在重载解析中给出令人惊讶的结果,因此通常好像 std::string 那样提供显式转换。


Mic*_*fik 5

Josuttis的书中说明如下:

出于安全原因,这是为了防止导致奇怪行为的非预期类型转换(类型char *通常具有奇怪的行为)和歧义(例如,在组合a string和C字符串的表达式中,它可以转换stringchar *反之亦然) .