函数的返回值通常存储在堆栈或寄存器中。但是对于大型结构,它必须在堆栈上。在真正的编译器中必须为此代码进行多少复制?还是优化掉了?
例如:
struct Data {
unsigned values[256];
};
Data createData()
{
Data data;
// initialize data values...
return data;
}
(假设函数不能内联..)
最佳答案
无;没有副本完成。
调用者的 Data 返回值的地址实际上作为隐藏参数传递给函数,createData 函数只是简单地写入调用者的堆栈帧。
这被称为 named return value optimisation .另见 c++ faq on this topic .
commercial-grade C++ compilers implement return-by-value in a way that lets them eliminate the overhead, at least in simple cases
...
When yourCode() calls rbv(), the compiler secretly passes a pointer to the location where rbv() is supposed to construct the "returned" object.
您可以通过将带有 printf 的析构函数添加到您的结构来证明这已完成。如果此按值返回优化正在运行,则应仅调用一次析构函数,否则调用两次。
您还可以检查程序集以查看是否发生了这种情况:
Data createData()
{
Data data;
// initialize data values...
data.values[5] = 6;
return data;
}
这是程序集:
__Z10createDatav:
LFB2:
pushl %ebp
LCFI0:
movl %esp, %ebp
LCFI1:
subl $1032, %esp
LCFI2:
movl 8(%ebp), %eax
movl $6, 20(%eax)
leave
ret $4
LFE2:
奇怪的是,它在堆栈上为数据项 subl $1032, %esp
分配了足够的空间,但请注意它采用堆栈上的第一个参数 8(%ebp)
作为对象的基地址,然后初始化该项目的元素 6。由于我们没有为 createData 指定任何参数,这很奇怪,直到您意识到这是指向父数据版本的 secret 隐藏指针。
关于c - C 编译器如何实现返回大型结构的函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2155730/