为了给函数提供修改向量的选项,我无法做到
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()
来电。所以每个小表现都很重要。
答案 0 :(得分:18)
您可以使用参考:
int &curr = myvec.at(i);
// do stuff with curr
at
成员函数确定边界检查以确保参数在vector
的大小范围内。分析只是确切地知道它比operator[]
慢多少的方法。在此处使用引用允许您执行一次查找,然后在其他位置使用结果。如果你想保护自己不会意外地改变价值,你可以把它作为const
的参考。
答案 1 :(得分:4)
从我自己的类似代码测试(在gcc和Linux下编译),operator[]
明显快于at
,不是因为边界检查,而是因为异常处理的开销。用我自己的边界检查at
(在越界范围内抛出异常)来替换在越界范围内引发assert,这给了一个可测量的改进。
使用引用,Kristo said,只允许您进行一次边界检查。
忽略边界检查和异常处理开销,operator[]
和at
都应优化为等效于直接数组访问或通过指针直接访问。
答案 2 :(得分:2)
运算符[]可能比at
更快,因为它不需要进行边界检查。
您可以curr
作为参考来做您想做的事。
MyClass & curr = myvec.at(i);
在担心之前,你也可能会做一些基准测试。现代处理器可以非常容易地每秒处理数千次操作。
答案 3 :(得分:2)
当性能成为问题时,无法替代性能分析。编译器的优化功能在不同版本之间变化,对源代码的微小,微不足道的改变可以极大地改变最终的性能。
除了你自己,没有人可以回答这个问题:创建一个测试工具,并在其上抛出几个算法,看看你得到了什么。
PS。如果性能确实是一个问题,那么,通过删除向量并用原始数组替换它,我从png解码器中获得了10倍的速度提升。同样,这是针对Visual Studio 6.我并不是说原始数组替换会给你一个10倍的改进,但它是值得尝试的。
答案 4 :(得分:2)
第一个不起作用的原因是你没有将指针或迭代器设置为第i个变量的地址。相反,你将curr设置为等于第i个变量的值,然后修改curr。我假设做了这个并且做了引用。
这样做:
MyObject& curr = myvec.at( i );
答案 5 :(得分:1)
我看到的选项,大致偏好的反向顺序:
[]
代替at()
。at()
一次,然后将其保存到参考文献中(请参阅上面的Kristo答案)。老实说,你应该做的是使用四种不同的方法,并使用产生最容易理解的代码的方法。在大多数情况下,我们很乐意牺牲一些机器周期来处理人类更容易维护的代码。
答案 6 :(得分:0)
at()
的复杂性是不变的,即在实践中这意味着它必须被设计为不会有任何相关的性能损失。
您可以使用[]
,这也是常量复杂,但不检查边界。这相当于使用指针算法,因此,可能比前者快一点。
无论如何,vector专门设计用于对其任何元素的持续性能访问。所以这应该是你最不担心的事情。
答案 7 :(得分:0)
矢量最适合访问速度。对于一般链表而言,对向量中的随机元素的访问是复杂的O(1),而对于链接树则是O(n)。
然而,这个问题是错误的,因为你的另一个问题的答案通过不解释如何通过使用引用来解决原始问题而导致你误入歧途。
答案 8 :(得分:0)
如果是这种情况,你加载一个向量,然后处理它而不添加或删除任何更多元素,然后考虑获取指向底层数组的指针,并使用数组操作来“避免向量开销”
如果要在处理过程中添加或删除元素,那么这样做是不安全的,因为矢量本身可以在任何点移动基础数组。