如果您创建一个函数,例如:
void SomeFunction(int* ptr){
int** ptr3 {&ptr};
std::cout << ptr3 << std::endl;
}
int main(){
int num{4};
int* ptr{&num};
std::cout << ptr << std::endl;
int** ptr2 {&ptr};
std::cout << ptr2 << std::endl;
SomeFunction(ptr);
}
当传递 ptr 指针作为参数时,其单元格会发生变化。即ptr值被复制?如果是这样,如果复制仍然发生,为什么这种传递数据的方法比按值传递更快?
是的,传递参数时,总是会发生复制。但值(指针或引用)的地址或值本身可以被复制。
所有函数参数都位于寄存器和堆栈中;此外,在编译时(通常)它们在堆栈上的偏移量是已知的,这允许编译函数。没有办法以任何其他方式传递一些东西(除了优化尾递归,但我们不会在这里讨论 - 我什至不知道它是否有优势)。
通常,当他们谈论出于优化目的而转移链接时,他们指的是转移大型结构。当传递指针时,会传递一个需要 8 个字节的地址(好吧,或者在 x32 上是 4 个字节),并且结构可以更大(另外,它可以有一个带有内存分配和一堆其他东西的复制构造函数)。
例如,当按向量值传输时,在堆栈上分配大约 20 个字节(我是从内存写入,我记不太清了),并且为其中的所有元素分配内存,然后将它们分配给堆栈。也复制了。显然这比简单地传递 8 字节指针要慢得多。
但是当传递像 int、long、double 这样的简单类型时,没有任何节省 - 相反,只有缺点。
由于两级取消引用,对通过引用传递的数据的访问可能会变慢,但情况并非总是如此。此外,对于值传递参数,编译器可能知道它与其他代码隔离,并对相同类型的其他数据(例如 sse)应用更多优化,而在指针的情况下,它必须确保线性如果指针指向相同的数据,则执行。在没有 pluses 的 C 中,甚至有一个关键字
restrict允许您将指针标记为与其他函数数据不相交,但在 pluses 中它被删除了。