为什么std :: string没有提供到const char*的转换?

Dov*_*eld 13 c++ string implicit-conversion

这更像是一个政策或历史问题.为什么决定为std :: string提供const char*转换?有人害怕有人可能会做printf("%s",s)并相信它会自动转换吗?关于这个问题有没有公开讨论?

Kar*_*nek 28

自动演员几乎总是邪恶的.如果有一个强制转换const char *,std::string也可以自动转换为其他指针类型,这可能导致很难找到错误.有c_str()返回的方法,const char *所以你仍然可以实现你所需要的.此外,类型转换在逻辑上不正确 - std::string不等同于const char *.

  • +1:同意.即使在标准库中,也存在可怕的强制转换过载的示例.例如,考虑`std :: ios :: operator void*`. (7认同)
  • @dov:如果你知道自己在做什么并自己编写派生的字符串类,那么它可能不是问题.但是在标准中拥有这个意味着每个人都具有这种投射功能 - 并不是每个人都意识到自动抛出陷阱,而不是注意到@ edA-qa mort-ora-y所描述的可能出现的性能问题. (4认同)
  • +1,如果字符串被破坏,指针指向什么? (2认同)
  • @dark_charlie - 如果强制转换可能会导致问题,那么 .c_str() 太多也会导致问题,因为我希望它们是等效的。无论如何,你是说这是两害相权取其轻...多年来我一直在使用带有自动转换的派生类,而且我还没有因此而遇到任何错误。但这也许是因为我没有将通用模板元编程与敏捷 Boost 类一起使用。:-) (2认同)
  • @Oli:虽然这个特定的例子可以追溯到安全bool成语被理解之前,并且使用显式运算符bool将该类型的用法替换为0x. (2认同)

edA*_*a-y 11

字符串类在内部不需要存储终止为0的字符串.事实上,如果它不想要它甚至不必将它们存储在连续的内存中.因此,隐式演员表没有意义,因为它可能是一项代价高昂的操作.

然后c_str()函数为您提供c-string.根据库在内部存储它的方式,此函数可能必须创建一个临时的.此临时值仅在您修改字符串之前有效.

不幸的是,因为字符串可以在内部被指定为c字符串.这不会导致任何功能损失,并允许隐式转换.

编辑标准基本上意味着内存是连续的(如果通过data()或[]运算符访问),虽然它不需要在内部,当然也不是空终止.可能所有实现都存储0.如果这是标准化的,则可以安全地定义隐式转换.

  • 实际上,我认为字符串类作为向量必须将其存储为连续内存. (3认同)
  • @Viktor:否.与`std :: vector`(其中为C++ 03引入了需求)不同,`std :: string`在调用`c_str()`之前不必使用连续存储.当然,从那里返回的指针必须指向连续的存储.我依稀记得一篇报道(也许是来自Herb Sutter?),C++ 0x WG进行了一次民意调查,并且没有人知道一个活跃的实现,*不会*总是使用连续的存储. (3认同)

Mat*_* M. 5

关于你以前的评论:

如果它们是等价的,那么使用强制转换而不是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...
}
Run Code Online (Sandbox Code Playgroud)