依赖于空std :: string的索引0是不是很糟糕?

bea*_*uxq 46 c++ stdstring

std::string my_string = "";
char test = my_string[0];
Run Code Online (Sandbox Code Playgroud)

我注意到这不会崩溃,每次我测试它,测试都是0.

我可以依赖它总是0吗?还是随意的?

这是不好的编程吗?

编辑:从一些评论中,我认为对此的有用性存在一些误解.

这样做的目的不是检查字符串是否为空.不需要检查字符串是否为空.

情况是有一个字符串可能是空的也可能不是.我只关心这个字符串的第一个字符(如果它不是空的).

在我看来,检查字符串是否为空是不太有效,然后,如果它不是空的,请查看第一个字符.

if (! my_string.empty())
    test = my_string[0];
else
    test = 0;
Run Code Online (Sandbox Code Playgroud)

相反,我只需查看第一个字符,无需检查字符串是否为空.

test = my_string[0];
Run Code Online (Sandbox Code Playgroud)

Bar*_*icz 68

C++ 14

没有; 你可以依靠它.

21.4.5.2(或[string.access])中我们可以找到:

返回:*(begin() + pos)if pos < size().否则,返回对charT具有value 的类型对象的引用charT(),其中修改对象会导致未定义的行为.

换句话说,当pos == size()(两者都为0时为真)时,运算符将返回对默认构造的字符类型的引用,禁止您修改该字符类型.

对于空(或0大小)字符串,它不是特殊的,并且对于每个长度都是相同的.


C++ 03

而且大多数肯定是 C++ 98.

这取决于.

这是官方ISO/IEC 14882 的21.3.4.1:

返回:If pos < size(),返回data()[pos].否则,如果pos == size(),const版本返回charT().否则,行为未定义.

  • 请注意,在C++ 11之前,`const []`的非const版本在这种情况下会导致未定义的行为(即使您不修改结果引用). (6认同)
  • @BenKey对于第一个引用,我使用了一个非常有用的[在线渲染(我认为)最后的C++ 14草案](http://eel.is/c++draft/string.access).对于第二个,它是原始的ISO PDF.正如Ben V.指出的那样,这两个数字代表的部分都是文件. (2认同)

ein*_*ica 31

@Bartek Banachewicz的答案解释了哪些情况允许你做出你的假设.我想补充一点

这是糟糕的编程.

为什么?有几个原因:

  1. 你必须成为一名语言律师才能确保这不是一个错误.如果不是这个页面,我不知道答案,坦率地说 - 我认为你也不应该知道.
  2. 没有字符串直觉的人是一个空终止的字符序列,在你阅读标准或询问他们的朋友之前,他们不知道你要做什么.
  3. 以不好的方式打破最小惊喜原则.
  4. 违背"写你的意思"的原则,即让代码表达问题域概念.
  5. 幻数的使用排序(在这种情况下,0是否实际构成幻数)是有争议的.

我要继续吗?......我几乎可以肯定你几乎在所有方面都有另一种优势.我甚至冒昧地猜测你已经做了一些"糟糕"的事情来操纵自己想做这件事.

永远记住:其他不会咨询你的人,迟早会需要维护这段代码.想想他们,不仅仅是你自己,谁能想出来.另外,从现在开始的十年间,谁会说你会记住你自己的伎俩?你可能是那个困惑的维护者......

  • 是否定义了行为:如果我读取类似于OP的前两行的代码,我会去WTF.请记住,即使在C++ 14中,您也不能*修改返回的引用,或者您再次使用UB.绝对糟糕,糟糕的风格. (3认同)
  • -1:编程也不错.定义了行为,就像s [-2]在许多语言中返回字符串中倒数第二个字符一样.是的,会有一些C++程序员不知道这个行为已定义,并且评论可能是有序的.但如果s [0]足够,我不会添加一行代码. (2认同)
  • @kevincline:定义某事的事实并不意味着应该使用它.实际上,需要对边缘情况进行特定定义的行为,可能会有所不同,这种行为通常(并非总是)更好地避免.此外,简洁性很好,但是:1.还有其他方法可以实现它.2.你仍然必须平衡简洁,而不仅仅是牺牲后者. (2认同)
  • 有些东西不会成为惯用语,因为一个人或少数人使用它.另外,我会说,一个好的成语最初并不会令人困惑. (2认同)