这更多是一个政策或历史问题。为什么决定不为 std::string 提供 const char * 转换?是否担心有人会执行 printf("%s", s) 并相信它会自动转换?有没有关于这个问题的公开讨论?
4 回答
自动施法几乎总是邪恶的。如果有转换为const char *
, astd::string
也可以自动转换为其他指针类型,这可能导致难以找到错误。有c_str()
返回的方法,const char *
所以你仍然可以实现你所需要的。此外,类型转换在逻辑上不正确 -std::string
不等同于const char *
.
字符串类在内部不需要存储以 0 结尾的字符串。事实上,如果它不想,它甚至不必将它们存储在连续的内存中。因此,隐式转换没有意义,因为它可能是一项代价高昂的操作。
然后 c_str() 函数为您提供 c 字符串。根据库在内部存储它的方式,此函数可能必须创建一个临时函数。此临时文件仅在您修改字符串之前有效。
然而不幸的是,因为一个字符串可以在内部被指定为一个 c 字符串。这不会导致任何功能损失,并允许隐式转换。
编辑该标准基本上暗示内存是连续的(如果通过 data() 或 [] 运算符访问),尽管它不需要在内部,当然也不是空终止。可能所有实现也存储 0。如果这是标准化的,那么可以安全地定义隐式转换。
关于您之前的评论:
如果它们是等价的,那么使用 cast 而不是 c_str() 调用没有区别(为了方便起见)
有一个非常重要的区别:一个是隐式的,另一个是显式的。
C++0x 引入了强制explicit
转换运算符的概念,但在此之前它们是隐式的,这意味着永远不清楚(在查看代码时)是否会使用它们。
隐式转换是不好的,特别是因为它们可以级联,导致代码极其晦涩。
此外,如前所述,这里存在正确性问题。因为返回的指针只有在对象不变的c_str
情况下才有效,那么你可能会发现自己很难找到错误。string
考虑:
void function()
{
std::map<int, char const*> map;
map[1] = boost::lexical_cast<std::string>(47);
std::cout << map[1] << std::endl; // CRASH here, if lucky...
}
我的感觉是 C++ 是一种强类型语言,隐式类型转换破坏了类型安全。
它通常会在转换发生在您意想不到的地方咬住您,并且会使您的代码难以调试。
非显式构造函数可以具有类似的效果,并且 std::string 本身确实具有来自 const char * 的隐式构造函数。在这种情况下,它不一定是一件坏事,尽管它会导致代码效率低下。