使用指针时是否会影响性能?
避免使用指针会更好吗?如果是,在什么情况下?显然,它们与引用一起有助于减少数据复制。我假设如果指向的数据类型很小,那么对指针的需求就会更小。相反,最好通过指针传递大对象,因为指针的开销小于复制对象的开销。
我还想知道参数/参数以外区域的指针?
在这种性能上下文中,引用通常比指针更好吗?
我很感激我正在接近微优化的“肮脏”主题,但我正在编写一个非常关注延迟的应用程序。
使用指针时是否会影响性能?
避免使用指针会更好吗?如果是,在什么情况下?显然,它们与引用一起有助于减少数据复制。我假设如果指向的数据类型很小,那么对指针的需求就会更小。相反,最好通过指针传递大对象,因为指针的开销小于复制对象的开销。
我还想知道参数/参数以外区域的指针?
在这种性能上下文中,引用通常比指针更好吗?
我很感激我正在接近微优化的“肮脏”主题,但我正在编写一个非常关注延迟的应用程序。
我知道性能可能很重要,但语义更重要:快速和错误是无用的。
使用指针或引用具有语义含义,例如共享:
void foo(A& a) {
a.a = 1;
if (a.b != 0) { throw ... }
a.b = 0;
}
在这种情况下a.b == 0
,第一个字段a
已更改,但第二个字段未更改。
此外,此类共享可能会产生潜在的混叠:
void foo(struct A a, struct A b);
void foo(struct A* a, struct A* b);
在第一种情况下,这两种结构必然是不同的,但在后一种情况下却不是。这种可能的别名可能会阻止优化。
首先关注语义。一旦你把它们做对了,你就可以在你的特定情况下调整和衡量效果。
在这种性能上下文中,引用通常比指针更好吗?
是的,尽可能使用引用,必要时使用指针。在性能方面,它们是相同的。
通常最好通过引用或指针传递大型结构以防止额外的复制,是的。
通过指针或引用访问变量或对象可能与直接访问它一样快。这种效率的原因在于微处理器的构造方式。在函数中声明的所有非静态变量和对象都存储在堆栈中,并且实际上是相对于堆栈指针进行寻址的。同样,在类中声明的所有非静态变量和对象都通过 C++ 中称为“this”的隐式指针访问。因此,我们可以得出结论,结构良好的 C++ 程序中的大多数变量实际上都是通过指针以一种或另一种方式访问的。因此,必须设计微处理器以使指针高效,这就是它们的本质。
虽然有一些缺点,但它们适用于指针和引用:
但是,使用指针和引用也有缺点。最重要的是,它需要一个额外的寄存器来保存指针或引用的值。寄存器是一种稀缺资源,尤其是在 32 位模式下。如果没有足够的寄存器,则每次使用时都必须从内存中加载指针,这会使程序变慢。另一个缺点是指针的值需要几个时钟周期才能访问指向的变量。
这里是来源。如果你问这个问题,我想你会发现它是一本好书。
让我们看一些代码:
int x = 0;
00412E0E mov dword ptr [x],0
foo(x);
00412E15 lea eax,[x]
00412E18 push eax
00412E19 call foo (4111C2h)
00412E1E add esp,4
foo(&x);
00412E21 lea eax,[x]
00412E24 push eax
00412E25 call foo (4111BDh)
00412E2A add esp,4
调用函数时没有区别。
void foo (int& x)
{
00411370 push ebp
00411371 mov ebp,esp
00411373 sub esp,0C0h
00411379 push ebx
0041137A push esi
0041137B push edi
0041137C lea edi,[ebp-0C0h]
00411382 mov ecx,30h
00411387 mov eax,0CCCCCCCCh
0041138C rep stos dword ptr es:[edi]
x = 3;
0041138E mov eax,dword ptr [x]
00411391 mov dword ptr [eax],3
}
void foo (int* x)
{
004117A0 push ebp
004117A1 mov ebp,esp
004117A3 sub esp,0C0h
004117A9 push ebx
004117AA push esi
004117AB push edi
004117AC lea edi,[ebp-0C0h]
004117B2 mov ecx,30h
004117B7 mov eax,0CCCCCCCCh
004117BC rep stos dword ptr es:[edi]
*x = 3;
004117BE mov eax,dword ptr [x]
004117C1 mov dword ptr [eax],3
}
功能内部没有区别。
这取决于指针指向的位置。如果在堆栈上分配对象并且您在许多情况下传递指针参数将比指向堆上对象的指针更快。如果您传递的对象在大多数机会已经被 CPU 缓存之前在函数中被积极使用,那么性能将大致相同。
关于复制... 大多数编译器将使用 CPU 寄存器来传递指针,这是 CPU 中可用的最快内存。但是,如果您将作为值传递,编译器将需要复制整个对象并调用 ctor / dtor。
所以我的建议是尝试将东西放在堆栈上并通过指针/引用传递。
很难说性能不是恒定的,并且可能会在不同的硬件/操作系统/编译器上发生变化,所以我的建议是使用分析器工具对代码进行分析,以分析缓存未命中、内存碎片、cpu 使用率等问题。
http://en.wikipedia.org/wiki/VTune
http://developer.amd.com/tools/CodeAnalyst/Pages/default.aspx
通过指针访问数据比直接访问数据要慢一些,但取消引用操作非常快,这通常没什么大不了的,除非您正在执行一些非常具体的重复数字运算任务。
关于传递大对象和小对象的指针,您是完全正确的。例如,int* 和 int 的大小可能相同,具体取决于实现。
引用和指针在性能方面通常是相同的。但是,如果您习惯使用 const Foo& 而不是 Foo*,编译器通常可以更好地优化您的代码。
您对基于堆的对象的最大问题是,当您需要它们时,它们通常不会放在一起,这意味着您需要更多时间将这些对象读入 CPU 缓存以处理它们(即,如果您有 10 个对象您需要使用的,如果它们都是连续分配的,则单个内存读取将一次性将它们全部推入缓存,如果它们分散在整个堆中,则需要对它们中的每一个进行读取)。
公平地说,这适用于所有堆系统,包括垃圾收集系统,即使在垃圾压缩之后也是如此。答案(显然)是将这些对象一起分配,或者提供一个带有空闲空间的缓冲区,以便随着时间的推移将它们分配到其中。
指针的另一个问题是您需要间接访问指针对象。如果你有一个对象数组,你很好——它们通常是连续的。但是,如果您有一个指针数组,则必须读取这些指针才能找出读取对象的位置。
现在,指针也可以很快——如果你使用指针算法来访问你的连续对象(因为你只需要读取一个指针来找出所有对象的位置)。
所以简而言之,问题不在于指针本身,而在于你如何组织它们指向的数据。
使用指针对性能没有影响。指针的使用非常快。在大多数(所有?)专业项目中,指针被用作常用工具。它们用于在任何地方构建列表、队列、地图、树、数据库。习惯他们!!!