在 C++11 及更高版本中,std::string::operator[] 是否进行边界检查?
In C++11 and beyond does std::string::operator[] do bounds checking?
我多次看到 std::string::operator[]
不做任何边界检查。即使 What is the difference between string::at and string::operator[]? 在 2013 年被问到,答案也说 operator[]
不做任何边界检查。
我的问题是,如果我查看 [[=31=]] 中的标准(在本例中为 draft N3797),我们有
const_reference operator[](size_type pos) const;
reference operator[](size_type pos);
- Requires:
pos <= size()
.
- Returns:
*(begin() + pos)
if pos < size()
. Otherwise, returns a reference to an object of type charT
with value charT()
, where modifying the object leads to undefined behavior.
- Throws: Nothing.
- Complexity: constant time.
这让我相信 operator[]
必须进行某种边界检查以确定它是否需要 return 字符串元素或默认值 charT
。这个假设是否正确,现在需要 operator[]
进行边界检查?
http://en.cppreference.com/w/cpp/string/basic_string/operator_at
Returns a reference to the character at specified location pos. No
bounds checking is performed.
(强调我的)。
如果你想要边界检查,使用std::basic_string::at
标准暗示实现需要提供边界检查,因为它基本上描述了未经检查的数组访问的作用。
如果您在范围内访问,则已定义。如果你走出去,你会触发未定义的行为。
这个标准容器的运算符模拟普通数组的运算符[]的行为。所以它不做任何检查。然而在调试模式下,相应的库可以提供这种检查。
如果要检查索引,请改用成员函数 at()
。
operator[]
has do some sort of bounds checking to determine...
不,不是。前提条件
Requires: pos <= size().
它可以假设它总是可以return字符串的一个元素。如果不满足此条件:未定义的行为。
operator[]
可能只会将指针从字符串的开头增加 pos。如果字符串更短,那么它只是 returns 对字符串后面数据的引用,无论它可能是什么。就像简单 C 数组中的经典越界。
为了完善 where pos == size()
的情况,它可以在其内部字符串数据的末尾分配一个额外的 charT
。因此,仅在不进行任何检查的情况下增加指针,仍会提供规定的行为。
措辞有点乱,仔细研究就会发现其实很准确。
上面写着:
- 前提是
[]
的参数要么是 = n 要么是 < n.
- 假设满足前提条件:
- 如果它是 < n,那么您会得到您要的字符。
- "Otherwise"(即如果它是 n)那么你得到
charT()
(即空字符)。
但是当你打破先决条件时没有定义规则,并且可以隐式满足对 = n 的检查(但没有明确要求be) 通过在位置 n.
实际存储一个 charT()
因此实现不需要执行任何边界检查……而常见的不需要。
首先,有一个requires子句。如果您违反了 requires 子句,您的程序将以未定义的方式运行。即pos <= size()
.
所以语言只定义了在那种情况下会发生什么。
下一段指出,对于 pos < size()
,它 returns 是对字符串中元素的引用。对于 pos == size()
,它 returns 对默认构造的 charT
的引用,其值为 charT()
.
虽然这看起来像是边界检查,但实际上实际发生的是 std::basic_string
分配了一个比要求的大一个缓冲区,并用 charT()
填充最后一个条目。然后[]
简单地做指针运算。
我试图想出一种方法来避免这种实现。虽然标准没有强制要求,但我无法说服自己存在替代方案。 .data()
有一些令人讨厌的东西,使得很难避免使用单个缓冲区。
我多次看到 std::string::operator[]
不做任何边界检查。即使 What is the difference between string::at and string::operator[]? 在 2013 年被问到,答案也说 operator[]
不做任何边界检查。
我的问题是,如果我查看 [[=31=]] 中的标准(在本例中为 draft N3797),我们有
const_reference operator[](size_type pos) const; reference operator[](size_type pos);
- Requires:
pos <= size()
.- Returns:
*(begin() + pos)
ifpos < size()
. Otherwise, returns a reference to an object of typecharT
with valuecharT()
, where modifying the object leads to undefined behavior.- Throws: Nothing.
- Complexity: constant time.
这让我相信 operator[]
必须进行某种边界检查以确定它是否需要 return 字符串元素或默认值 charT
。这个假设是否正确,现在需要 operator[]
进行边界检查?
http://en.cppreference.com/w/cpp/string/basic_string/operator_at
Returns a reference to the character at specified location pos. No bounds checking is performed.
(强调我的)。
如果你想要边界检查,使用std::basic_string::at
标准暗示实现需要提供边界检查,因为它基本上描述了未经检查的数组访问的作用。
如果您在范围内访问,则已定义。如果你走出去,你会触发未定义的行为。
这个标准容器的运算符模拟普通数组的运算符[]的行为。所以它不做任何检查。然而在调试模式下,相应的库可以提供这种检查。
如果要检查索引,请改用成员函数 at()
。
operator[]
has do some sort of bounds checking to determine...
不,不是。前提条件
Requires: pos <= size().
它可以假设它总是可以return字符串的一个元素。如果不满足此条件:未定义的行为。
operator[]
可能只会将指针从字符串的开头增加 pos。如果字符串更短,那么它只是 returns 对字符串后面数据的引用,无论它可能是什么。就像简单 C 数组中的经典越界。
为了完善 where pos == size()
的情况,它可以在其内部字符串数据的末尾分配一个额外的 charT
。因此,仅在不进行任何检查的情况下增加指针,仍会提供规定的行为。
措辞有点乱,仔细研究就会发现其实很准确。
上面写着:
- 前提是
[]
的参数要么是 = n 要么是 < n. - 假设满足前提条件:
- 如果它是 < n,那么您会得到您要的字符。
- "Otherwise"(即如果它是 n)那么你得到
charT()
(即空字符)。
但是当你打破先决条件时没有定义规则,并且可以隐式满足对 = n 的检查(但没有明确要求be) 通过在位置 n.
实际存储一个charT()
因此实现不需要执行任何边界检查……而常见的不需要。
首先,有一个requires子句。如果您违反了 requires 子句,您的程序将以未定义的方式运行。即pos <= size()
.
所以语言只定义了在那种情况下会发生什么。
下一段指出,对于 pos < size()
,它 returns 是对字符串中元素的引用。对于 pos == size()
,它 returns 对默认构造的 charT
的引用,其值为 charT()
.
虽然这看起来像是边界检查,但实际上实际发生的是 std::basic_string
分配了一个比要求的大一个缓冲区,并用 charT()
填充最后一个条目。然后[]
简单地做指针运算。
我试图想出一种方法来避免这种实现。虽然标准没有强制要求,但我无法说服自己存在替代方案。 .data()
有一些令人讨厌的东西,使得很难避免使用单个缓冲区。