gpt4 book ai didi

c++ - 通过引用开销访问与复制开销

转载 作者:搜寻专家 更新时间:2023-10-31 00:25:54 24 4
gpt4 key购买 nike

假设我想传递一个 POD 对象作为常量参数。我知道对于像 int 和 double 这样的简单类型,通过值传递比通过 const 引用更好,因为引用开销。但在多大尺寸时才值得作为引用?

struct arg
{
...
}

void foo(const arg input)
{
// read from input
}

void foo(const arg& input)
{
// read from input
}

即,我应该在多大的 struct arg 开始使用后一种方法?

我还应该指出,我在这里不是在谈论复制省略。让我们假设它不会发生。

最佳答案

TL;DR:这在很大程度上取决于目标架构、编译器和调用函数的上下文。如果不确定,分析并手动检查生成的代码。

如果函数是内联的,一个好的优化编译器可能会在两种情况下发出完全相同的代码。

但是,如果函数内联,则大多数 C++ 实现上的 ABI 规定将 const& 参数作为指针传递。这意味着该结构必须存储在 RAM 中,这样才能获得它的地址。这会对小对象的性能产生重大影响。

我们以x86_64 Linux G++ 8.2为例...

具有2 个成员的结构:

struct arg
{
int a;
long b;
};

int foo1(const arg input)
{
return input.a + input.b;
}

int foo2(const arg& input)
{
return input.a + input.b;
}

已生成 assembly :

foo1(arg):
lea eax, [rdi+rsi]
ret
foo2(arg const&):
mov eax, DWORD PTR [rdi]
add eax, DWORD PTR [rdi+8]
ret

第一个版本完全通过寄存器传递结构,第二个版本通过堆栈..

现在让我们尝试3 个成员:

struct arg
{
int a;
long b;
int c;
};

int foo1(const arg input)
{
return input.a + input.b + input.c;
}

int foo2(const arg& input)
{
return input.a + input.b + input.c;
}

已生成 assembly :

foo1(arg):
mov eax, DWORD PTR [rsp+8]
add eax, DWORD PTR [rsp+16]
add eax, DWORD PTR [rsp+24]
ret
foo2(arg const&):
mov eax, DWORD PTR [rdi]
add eax, DWORD PTR [rdi+8]
add eax, DWORD PTR [rdi+16]
ret

虽然使用第二个版本仍然会慢一点,因为它需要将地址放入 rdi 中,但没有太大区别。

那么真的很重要吗?

通常不会。如果您关心某个特定函数的性能,它可能会被频繁调用,因此很小。因此,它很可能是内联

让我们尝试调用上面的两个函数:

int test(int x)
{
arg a {x, x};
return foo1(a) + foo2(a);
}

已生成 assembly :

test(int):
lea eax, [0+rdi*4]
ret

瞧。现在一切都没有意义了。编译器将这两个函数内联并合并为一条指令!

关于c++ - 通过引用开销访问与复制开销,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54573330/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com