C++向量 at/[] 操作员速度

发布于 2024-08-27 21:32:59 字数 477 浏览 4 评论 0原文

为了给函数提供修改向量的选项,我不能这样做,

curr = myvec.at( i );
doThis( curr );
doThat( curr );
doStuffWith( curr );

但我必须这样做:(

doThis( myvec.at( i ) );
doThat( myvec.at( i ) );
doStuffWith( myvec.at( i ) );

正如我其他问题的答案所指出的那样)

  • 我将大量调用 myvec.at() 然后。与第一个使用变量存储结果的示例相比,它有多快?

  • 我还有其他选择吗?我可以以某种方式使用指针吗?

当情况变得严重时,每秒将有数千次对 myvec.at() 的调用。所以每一个小表演者都很重要。

In order to give functions the option to modify the vector I can't do

curr = myvec.at( i );
doThis( curr );
doThat( curr );
doStuffWith( curr );

But I have to do:

doThis( myvec.at( i ) );
doThat( myvec.at( i ) );
doStuffWith( myvec.at( i ) );

(as the answers of my other question pointed out)

  • I'm going to make a hell lot of calls to myvec.at() then. How fast is it, compared to the first example using a variable to store the result?

  • Is there a different option for me? Can I somehow use pointers?

When it's getting serious there will be thousands of calls to myvec.at() per second. So every little performance-eater is important.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

蓝眼睛不忧郁 2024-09-03 21:33:00

您可以使用引用:

int &curr = myvec.at(i);
// do stuff with curr

at 成员函数执行边界检查,以确保参数在 vector 的大小范围内。分析是准确了解它与 operator[] 相比慢了多少的唯一方法。此处使用引用允许您执行一次查找,然后在其他地方使用结果。如果您想防止意外更改该值,则可以将其设为对 const 的引用。

You can use a reference:

int &curr = myvec.at(i);
// do stuff with curr

The at member function does bounds checking to make sure the argument is within the size of the vector. Profiling is only way to know exactly how much slower it is compared to operator[]. Using a reference here allows you to do the lookup once and then use the result in other places. And you can make it a reference-to-const if you want to protect yourself from accidentally changing the value.

风吹过旳痕迹 2024-09-03 21:33:00

根据我自己对类似代码(在 gcc 和 Linux 下编译)的测试,operator[] 明显比 at 更快,不是因为边界检查,而是因为异常处理的开销。将 at (在越界时引发异常)替换为我自己的边界检查,引发 断言给出了可测量的改进。

使用引用,正如 Kristo 所说,让你只招致界限检查一次开销。

忽略边界检查和异常处理开销,operator[]at 都应该优化为相当于直接数组访问或通过指针直接访问。

不过,正如 Chris Becke 所说,分析是无可替代的。

From my own tests with similar code (compiled under gcc and Linux), operator[] can be noticeably faster than at, not because of the bounds checking, but because of the overhead of exception handling. Replacing at (which throws an exception on out-of-bounds) with my own bounds checking that raised an assert on out-of-bounds gave a measurable improvement.

Using a reference, as Kristo said, lets you only incur the bounds checking overhead once.

Ignoring bounds checking and exception handling overhead, both operator[] and at should be optimized to equivalent to direct array access or direct access via pointer.

As Chris Becke said, though, there's no substitute for profiling.

2024-09-03 21:33:00

当性能成为问题时,分析是无可替代的。编译器的优化能力因版本而异,对源代码的微小、无关紧要的更改可能会极大地改变最终的性能。

除了你自己之外,没有人能回答这个问题:创建一个测试工具,并向其抛出多种算法,看看会得到什么。

附注如果性能确实是一个问题,那么,我通过删除向量并用原始数组替换它们,将 png 解码器的速度提高了 10 倍。同样,这是针对 Visual Studio 6 的。我并不是说原始数组替换会给您带来 10 倍的改进,但这是值得尝试的事情。

When performance is an issue, there is no substitute for profiling. The optimization capabilities of compilers change from version to version, and tiny, insignificant alterations to source code can dramatically change the resulting performace.

No one can answer this question but yourself: Create a test harness, and throw several algorithms at it and see what you get.

ps. if performance really is an issue, well, i got a factor 10 speed increase out of a png decoder by removing the vectors and replacing them with raw arrays. Again, this was for Visual Studio 6. I am not claiming that a raw array substitution will give you a factor 10 improvement, but it is something to try.

街道布景 2024-09-03 21:33:00

第一个不起作用的原因是您没有设置指向第 i 个变量的地址的指针或迭代器。相反,您将 curr 设置为等于第 i 个变量的值,然后修改 curr。我假设 doThis 和 doThat 是引用。

这样做:

MyObject& curr = myvec.at( i );

The reason the first doesn't work is that you're not setting a pointer or iterator to the address of the ith variable. Instead you're setting curr equal to the value of the ith variable and then modifying curr. I'm assuming that doThis and doThat are references.

Do this:

MyObject& curr = myvec.at( i );
緦唸λ蓇 2024-09-03 21:33:00

Operator[] 可能比 at 更快,因为它不需要进行边界检查。

您可以将 curr 作为参考来执行您想要的操作。

MyClass & curr = myvec.at(i);

在担心之前,您也可以做一些基准测试。现代处理器每秒可以轻松处理数千次操作。

Operator[] might be faster than at, because it isn't required to do bounds checking.

You can make curr a reference to do what you want.

MyClass & curr = myvec.at(i);

You might also do some benchmarking before getting worried. Modern processors can handle thousands of operations per second quite easily.

潦草背影 2024-09-03 21:33:00

我看到的选项,大致偏好的相反顺序

  1. 将指针存储在容器中而不是实际的对象中。无论如何,如果对象足够复杂以至于复制它们会出现问题,那么这可能是可取的。
  2. 使用索引运算符 [] 而不是 at()
  3. 只需调用 at() 一次,并将其保存到引用中(请参阅上面 Kristo 的回答)。
  4. 忘记它,直到您确实遇到运行时间过长的问题。如果发生这种情况,请首先分析您的代码以确保瓶颈就在这里,然后才担心执行上述其中一项来加快速度。

老实说,您应该做的是尝试四种不同的方法,并只使用生成最容易理解的代码的方法。在大多数情况下,我们很乐意牺牲一些机器周期来获得更易于人类维护的代码。

Options that I see, in roughly inverse order of preference:

  1. Store pointers in your container instead of the actual objects. This may be advisable anyway, if the objects are complex enough that copying them around is problematic.
  2. Use the indexing operator [] instead of at().
  3. Just call at() once, and save it into a reference (see Kristo's answer above).
  4. Forget about it until you actually have a problem with excessive runtime. If that happens, profile your code first to make sure the bottleneck is here, and only then worry about doing one of the above to speed things up.

Honestly, what you should do is play with the four different approaches, and just use the one that produces the easiest to understand code. In most cases we are happy to sacrifice a few machine cycles for code that is easier for human beings to maintain.

荒人说梦 2024-09-03 21:33:00

at() 的复杂度是恒定的,即,在实践中,这意味着它必须被设计为不具有任何相关的性能损失。

您可以使用[],它也是恒定的复杂度,但不检查边界。这相当于使用指针算术,因此可能比前者快一点。

无论如何,向量都是专门为对其任何元素进行持续性能访问而设计的。所以这应该是您最不用担心的。

The complexity of at() is constant, i.e., in practice this means that it must be designed to not have any relevant performance penalty.

You can use [], which is also constant complexity, but does not check bounds. This would be equivalent to using pointer arithmetic and, thus, potentially a bit faster than the former.

In any case, vector is specifically designed for constant performance access to any of its elements. So this should be the least of your worries.

凡间太子 2024-09-03 21:33:00

矢量最适合访问速度。与一般链表的 O(n) 和链接树的 O(log n) 相比,访问向量中的随机元素的复杂度为 O(1)。

然而,这个问题是错误的,因为您的其他问题的答案没有解释如何通过使用参考来解决您的原始问题,从而使您误入歧途。

Vectors are the most suited for access speed. Access to a random element in a vector is of complexity O(1) compared with O(n) for general linked-lists and O(log n) for link-trees.

However this question is mis-placed as the answer to your other question has lead you astray by not explaining how to fix your original problem by using a reference.

围归者 2024-09-03 21:33:00

如果是这种情况,您加载一个向量,然后处理它而不添加或删除任何更多元素,然后考虑获取指向底层数组的指针,并对其使用数组操作来“避免向量开销”。

如果您在处理过程中添加或删除元素,那么这样做是不安全的,因为底层数组可能会被向量本身在任何点移动。

If it is the case, that you load up a vector, then process it without adding or deleting any more elements, then consider getting a pointer to the underlying array, and using array operations on that to 'avoid the vector overhead'.

If you are adding or deleting elements as part of your processing, then this is not safe to do, as the underlying array may be moved at any point by the vector itself.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文