简体   繁体   English

在C ++ 11及更高版本中,std :: string :: operator []是否进行边界检查?

[英]In C++11 and beyond does std::string::operator[] do bounds checking?

I have seen many times that std::string::operator[] does not do any bounds checking. 我已经多次看到std::string::operator[]没有进行任何边界检查。 Even What is the difference between string::at and string::operator[]? 甚至string :: at和string :: operator []之间有什么区别? , asked in 2013, the answers say that operator[] does not do any bounds checking. 在2013年问道,答案说operator[]没有做任何边界检查。

My issue with this is if I look at the standard (in this case draft N3797 ) in [string.access] we have 我的问题是,如果我在[string.access]中查看标准(在本例中为草案N3797

 const_reference operator[](size_type pos) const; reference operator[](size_type pos); 
  1. Requires: pos <= size() . 需要: pos <= size()
  2. Returns: *(begin() + pos) if pos < size() . 如果pos < size()返回: *(begin() + pos) pos < size() Otherwise, returns a reference to an object of type charT with value charT() , where modifying the object leads to undefined behavior. 否则,返回对charT类型的对象的引用,其值为charT() ,其中修改对象会导致未定义的行为。
  3. Throws: Nothing. 投掷:没什么。
  4. Complexity: constant time. 复杂性:恒定时间。

This leads me to believe that operator[] has to do some sort of bounds checking to determine if it needs to return a element of the string or a default charT . 这让我相信operator[]必须进行某种边界检查以确定它是否需要返回字符串的元素或默认的charT Is this assumption correct and operator[] is now required to do bounds checking? 这个假设是否正确,现在需要operator[]进行边界检查?

The wording is slightly confusing, but if you study it in detail you'll find that it's actually very precise. 措辞有点令人困惑,但如果你仔细研究它,你会发现它实际上非常精确。

It says this: 它说:

  • The precondition is that the argument to [] is either = n or it's < n . 前提条件是[]的参数要么是= n,要么是< n
  • Assuming that precondition is satisfied: 假设满足前提条件:
    • If it's < n then you get the character you asked for. 如果它< n那么你得到你要求的角色。
    • "Otherwise" (ie if it's n ) then you get charT() (ie the null character). “否则”(即如果它是n )那么你得到charT() (即空字符)。

But no rule is defined for when you break the precondition, and the check for = n can be satisfied implicitly (but isn't explicitly mandated to be) by actually storing a charT() at position n . 但是,没有规则,当你打破的前提条件定义,并在检查= n可以隐含成立时(但不明确授权是)通过实际存储charT()的位置n。

So implementations don't need to perform any bounds checking… and the common ones won't. 因此,实现不需要执行任何边界检查......而常见的则不会。

operator[] has do some sort of bounds checking to determine... operator[]做了某种界限检查以确定......

No it doesn't. 不,不。 With the precondition 有前提条件

Requires: pos <= size(). 需要:pos <= size()。

it can just ASSUME that it can always return an element of the string. 它可以只是ASSUME它总是可以返回字符串的元素。 If this condition isn't met: Undefined behaviour. 如果不满足此条件:未定义的行为。

The operator[] will likely just increment the pointer from the start of the string by pos. operator[]可能只是通过pos从字符串的开头递增指针。 If the string is shorter, well then it just returns a reference to the data behind the string, whatever it might be. 如果字符串更短,那么它只是返回对字符串后面的数据的引用,无论它是什么。 Like a classic out of bounds in simple C arrays. 就像简单C数组中的经典界限一样。

To fullify the case of where pos == size() it could just have allocated an extra charT at the end of its internal string data. 为了完整pos == size()的情况,它可能只是在其内部字符串数据的末尾分配了一个额外的charT So just incrementing the pointer without any checks, would still deliver the stated behaviour. 因此,只需在没有任何检查的情况下递增指针,仍然会提供所述行为。

First, there is a requires clause. 首先,有一个要求条款。 If you violate the requires clause, your program behaves in an undefined manner. 如果违反了requires子句,则程序的行为方式不确定。 That is pos <= size() . 那是pos <= size()

So the language only defines what happens in that case. 所以语言只定义了那种情况下发生的事情。

The next paragraph states that for pos < size() , it returns a reference to an element in the string. 下一段说明对于pos < size() ,它返回对字符串中元素的引用。 And for pos == size() , it returns a reference to a default constructed charT with value charT() . 对于pos == size() ,它返回对值为charT()的默认构造charT的引用。

While this may look like bounds checking, in practice what actually happens is that the std::basic_string allocates a buffer one larger than asked and populates the last entry with a charT() . 虽然这可能看起来像边界检查,但实际上实际发生的是std::basic_string分配一个大于charT()的缓冲区并用charT()填充最后一个条目。 Then [] simply does pointer arithemetic. 然后[]只做指针arithemetic。

I have tried to come up with a way to avoid that implementation. 我试图想出一种避免这种实现的方法。 While the standard does not mandate it, I could not convince myself an alternative exists. 虽然标准没有强制要求,但我无法说服自己存在替代方案。 There was something annoying with .data() that made it difficult to avoid the single buffer. 有一些令人烦恼的.data()使得很难避免使用单个缓冲区。

This operator of standard containers emulates the behavior of the operator [] of ordinary arrays. 这个标准容器的运算符模拟普通数组的operator []的行为。 So it does not make any checks. 所以它不做任何检查。 However in the debug mode the corresponding library can provide this checking. 但是在调试模式下,相应的库可以提供此检查。

If you want to check the index then use member function at() instead. 如果要检查索引,请使用at()成员函数。

http://en.cppreference.com/w/cpp/string/basic_string/operator_at http://en.cppreference.com/w/cpp/string/basic_string/operator_at

Returns a reference to the character at specified location pos. 返回对指定位置pos处的字符的引用。 No bounds checking is performed. 不执行边界检查。

(Emphasis mine). (强调我的)。

If you want bounds checking, use std::basic_string::at 如果要进行边界检查,请使用std :: basic_string :: at

The standard imply the implementation needs to provide bounds checking because it basically describes what an unchecked array access does. 该标准意味着实现需要提供边界检查,因为它基本上描述了未经检查的数组访问所做的事情。

If you access within bounds, it's defined. 如果您在边界内访问,则会定义它。 If you step outside, you trigger undefined behavior. 如果你走出去,你会触发未定义的行为。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM