Lih*_*ihO 79 c++ stl stdvector
我知道这at()
比[]
它的边界检查慢,这也在类似的问题中讨论,如C++ Vector at/[] operator speed 或:: std :: vector :: at()vs operator [] << Surprising results !! 速度慢5到10倍!.我只是不明白这种at()
方法有什么用处.
如果我有一个像这样的简单向量:std::vector<int> v(10);
我决定通过使用at()
而不是[]
在我有索引的情况下访问它的元素i
并且我不确定它是否在向量范围内,它迫使我用try-catch包装它块:
try
{
v.at(i) = 2;
}
catch (std::out_of_range& oor)
{
...
}
Run Code Online (Sandbox Code Playgroud)
虽然我能够通过自己使用size()
和检查索引来获得相同的行为,这对我来说似乎更容易和方便:
if (i < v.size())
v[i] = 2;
Run Code Online (Sandbox Code Playgroud)
所以我的问题是:
使用vector :: at over vector :: operator []有什么好处?
我什么时候应该使用vector :: at而不是vector :: size + vector :: operator []?
pmd*_*mdj 63
我会说vector::at()
抛出的异常并不是真正意图被周围的代码捕获.它们主要用于捕获代码中的错误.如果您需要在运行时进行边界检查,因为例如索引来自用户输入,那么您最好使用if
语句.总而言之,设计你的代码的目的是vector::at()
永远不会抛出异常,这样如果确实如此,你的程序就会中止,这就是bug的标志.(就像一个assert()
)
Ale*_* C. 16
它迫使我用try-catch块包装它
不,它没有(try/catch块可以在上游).当您希望抛出异常而不是程序进入未定义的行为领域时,它非常有用.
我同意大多数越界访问向量是程序员的错误(在这种情况下,你应该使用assert
更容易找到这些错误;标准库的大多数调试版本会自动为你执行此操作).您不希望使用可以向上游吞下的异常来报告程序员错误:您希望能够修复该错误.
因为对于向量的越界访问不太可能是正常程序流的一部分(在它是的情况下,你是对的:事先检查size
而不是让异常冒泡),我同意你的诊断:at
基本没用.
Ton*_*roy 11
使用vector :: at over vector :: operator []有什么好处?我什么时候应该使用vector :: at而不是vector :: size + vector :: operator []?
这里重要的一点是异常允许将正常的代码流与错误处理逻辑分离,并且单个catch块可以处理从无数抛出站点生成的问题,即使它们分散在函数调用的深处.因此,at()
对于单次使用而言,这并不一定更容易,但是当您需要大量索引进行验证时,有时它会变得更容易 - 并且不会混淆正常情况逻辑.
值得注意的是,在某些类型的代码中,索引以复杂的方式递增,并且不断用于查找数组.在这种情况下,确保使用正确的检查要容易得多at()
.
作为一个真实世界的例子,我有代码将C++标记为词法元素,然后是将标记移动到标记向量的其他代码.根据遇到的情况,我可能希望增加并检查下一个元素,如:
if (token.at(i) == Token::Keyword_Enum)
{
ASSERT_EQ(tokens.at(++i), Token::Idn);
if (tokens.at(++i) == Left_Brace)
...
or whatever
Run Code Online (Sandbox Code Playgroud)
在这种情况下,很难检查您是否已经不恰当地到达输入的末尾,因为这非常依赖于遇到的确切令牌.在每个使用点进行明确检查是痛苦的,并且程序员错误的余地更多,因为前/后增量,使用点的偏移,关于某些早期测试等的持续有效性的错误推理.
at
如果您有指向向量的指针,则可以更清楚:
return pVector->at(n);
return (*pVector)[n];
return pVector->operator[](n);
Run Code Online (Sandbox Code Playgroud)
除了性能,第一个是更简单明了的代码。
首先,是否at()
或operator[]
没有指定慢的.当没有边界错误时,我希望它们的速度大致相同,至少在调试版本中是这样.区别在于at()
确切地指出了在边界错误(异常)中会发生什么,在这种情况下operator[]
,它是未定义的行为 - 在我使用的所有系统(g ++和VC++)中崩溃,至少当使用正常的调试标志.(另一个不同之处在于,一旦我确定了我的代码,我可以operator[]
通过关闭调试来大幅提高速度.如果性能需要它 - 除非必要,否则我不会这样做.)
在实践中,at()
很少适合.如果上下文是这样的,你知道索引可能是无效的,你可能想要显式测试(例如,返回默认值或其他东西),如果你知道它不能无效,你想要中止(如果你不知道它是否可以无效,我建议你更精确地指定你的函数的界面.但是,有一些例外,其中无效索引可能是由解析用户数据引起的,而错误应该导致整个请求的中止(但不会导致服务器关闭); 在这种情况下,例外情况是适当的,并且at()
会为您做到这一点.
归档时间: |
|
查看次数: |
46197 次 |
最近记录: |