代码之家  ›  专栏  ›  技术社区  ›  Dustin Getz sunsations

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

  •  31
  • Dustin Getz sunsations  · 技术社区  · 16 年前

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

    获取等效的C字符串

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

    终止空字符为 自动附加。

    返回的数组指向 内部位置与所需 此序列的存储空间 字符及其终止符 空字符,但此中的值 数组不应在 计划,只允许留下来 保持不变,直到下一次呼叫 非常数成员函数 字符串对象。

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

    7 回复  |  直到 13 年前
        1
  •  28
  •   user7116    16 年前

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

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

        2
  •  20
  •   Drew Dormann    6 年前

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

    • 即使是明确的转换 c_str() provides本身就很危险。我见过很多情况,在原始字符串对象的生命周期结束后(或者对象被修改从而使指针无效),指针被存储以供使用。通过明确呼吁 c_str() 希望你知道这些问题。但使用隐式转换很容易导致未定义的行为,如:

      const char *filename = string("/tmp/") + name;
      ofstream tmpfile(filename); // UB
    • 在某些情况下,转换也会发生,在这些情况下,你不会想到它,至少可以说,语义是令人惊讶的:

      string name;
      if (name) // always true
       ;
      name-2; // pointer arithmetic + UB
      这些可以通过某种方式避免,但为什么一开始就陷入这种麻烦呢?
        3
  •  5
  •   Stack Overflow is garbage    16 年前

    因为隐式转换几乎永远不会像你期望的那样。它们可以在过载分辨率方面给出令人惊讶的结果,所以 通常 最好像std::string那样提供显式转换。

        4
  •  5
  •   Michael Kristofik    16 年前

    Josuttis的书说:

    这是出于安全原因,以防止意外的类型转换导致奇怪的行为(类型 char * 通常具有奇怪的行为)和歧义(例如,在一个结合了 string 以及可以转换的C铃声 一串 到…里面 char* 反之亦然)。

        5
  •  4
  •   Evg    5 年前

    除了规范中提供的基本原理之外(意外的惊喜),如果您将C API调用与 std::string ,你真的需要养成使用 ::c_str() 方法。如果你调用过varargs函数(例如: printf ,或同等),这需要 const char* ,然后你通过一个 std::string 直接(不调用提取方法),您不会得到编译错误(没有对varargs函数进行类型检查),但会得到运行时错误(类布局与二进制不完全相同) const字符* ).

    顺便说一句, CString (在MFC中)采取了相反的方法:它具有隐式强制转换,类布局与 const字符* (或 const w_char* ,如果编译为宽字符串,即:“Unicode”)。

        6
  •  2
  •   jpalecek    16 年前

    这可能是因为这种转换会有令人惊讶和奇特的语义。特别是你引用的第四段。

    另一个原因是存在隐式转换 const char* -> string ,而这恰恰相反,这意味着wrt重载解析的行为很奇怪(你不应该同时进行隐式转换 A->B B->A ).

        7
  •  1
  •   hyperboreean    16 年前

    因为C风格的字符串是错误和许多安全问题的来源,所以最好显式地进行转换。