如何解决在 Linux/x86-84 上传递大对象的 C++ 调用约定
我试图了解在 C++/Linux/x86-64 平台中按值传递对象作为函数参数的开销。
我用于探索的实验代码发布在下面和 Godbolt.org 上:https://godbolt.org/z/r9Yfv4
假设函数是一元的。我观察到的是:
- 如果参数对象的大小为 8 字节,则将其放入 RDI。
- 如果参数大小为 16 字节(每 8 字节包含两个子对象),则将这两个子对象放入 RDI 和 RSI。
- 如果参数大于 16 字节,它将通过堆栈传递。
我只考虑整型和指针以及这些基本类型的组合类型。我知道传递浮动/双打是不同的。
-imatch
的大小为 32 字节(GCC/Linux 实现,long + long + 指针 + 指针 = 32 字节。)。因此,按值传递 -match
应该类似于我的代码中定义的传递 std::function
。但是输出程序集显示 pass std::function
与 pass struct Person4
非常不同。看起来 std::function 是通过指针传递的,对吗?为什么会有这样的差异?
std::function
解决方法
你要阅读的文档是System V ABI for x86-64,特别是3.2.3节 «参数传递»
> 32 字节的结构总是在堆栈上。 对于
合并后清理说,如果大小大于 2 个 eighbytes(16 个字节),并且第一个参数不是 SSE,或者任何其他参数都不是 SSEUP,则整个聚合被归类为 MEMORY(堆栈) .
关于 std::function
的使用,最后一条规则可以解释它:
- 如果一个 C++ 对象有一个非平凡的复制构造函数或一个非平凡的析构函数,它会通过不可见的引用( 对象在参数列表中被具有类的指针替换 整数)
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。