在不实例化局部变量的情况下将结构传递给函数的效率

时间:2016-07-05 15:33:20

标签: c++ struct local pass-by-value

我最近了解到,我可以通过将结构传递给C ++中的函数来执行以下操作:

(我很抱歉没有使用更合适的名称"功能"在标题中,随时纠正我)

#include <iostream>

typedef struct mystruct{
    int data1;
    int data2;
} MYSTRUCT;

void myfunction( MYSTRUCT _struct ){
    std::cout << _struct.data1 << _struct.data2;
}

int main(){
    //This is what I recently learned
    myfunction( MYSTRUCT{2,3} );
    return 0;
}

这让我觉得这比实例化本地MYSTRUCT要便宜 并通过值传递给函数?或者只是一个方便的方法来做同样的事情,只是事后才消除临时变量?

例如,添加此行#define KBIG 10000000是:

std::vector<MYSTRUCT> myvector1;
for (long long i = 0; i < KBIG; i++) {
    myvector1.push_back(MYSTRUCT{ 1,1 });
}

始终比这更快:

std::vector<MYSTRUCT> myvector2;
for (long long i = 0; i < KBIG; i++) {
    MYSTRUCT localstruct = { 1,1 };
    myvector2.push_back(localstruct);
}

我试过测试它,但结果非常不一致,每个都徘徊在9-12秒左右。有时第一个会更快,有时则不会。当然,这可能是由于我在测试时的所有后台进程。

3 个答案:

答案 0 :(得分:3)

稍微简化并编译成汇编程序:

extern void emit(int);

typedef struct mystruct{
    int data1;
    int data2;
} MYSTRUCT;

__attribute__((noinline))
void myfunction( MYSTRUCT _struct ){
  emit(_struct.data1);
  emit(_struct.data2);
}

int main(){
    //This is what I recently learned
    myfunction( MYSTRUCT{2,3} );
    return 0;
}

有-O2收益率:

myfunction(mystruct):
        pushq   %rbx
        movq    %rdi, %rbx
        call    emit(int)
        sarq    $32, %rbx
        movq    %rbx, %rdi
        popq    %rbx
        jmp     emit(int)
main:
        movabsq $12884901890, %rdi
        subq    $8, %rsp
        call    myfunction(mystruct)
        xorl    %eax, %eax
        addq    $8, %rsp
        ret

发生了什么事?

编译器意识到整个结构适合寄存器并以这种方式传递给它。

故事的道德:表达意图。让编译器担心细节。

如果您需要副本,则需要副本。故事结束。

答案 1 :(得分:1)

如果速度有任何问题,请测量复制与使用const ref(即const MYSTRUCT& _struct)。进行测量时,请确保进行测量&lt; 1&gt; &lt; 2&gt;,然后&lt; 2&gt; &LT 1为卤素;以补偿缓存效果。

建议:避免使用_作为参数的第一个字符,因为一些保留字以它开头;另外,不要大写struct。

答案 2 :(得分:0)

如果你想加速你的代码,我建议你通过const引用传递结构,如下所示:

void myfunction (const MYSTRUCT& _struct)
{
    std::cout << _struct.data1 << _struct.data2;
}

这比传递值要快得多,因为它不会复制整个结构,而只会传递它的地址。

(好吧,在这种情况下不会有太大的区别,因为你的结构只包含2个整数,但你有> 1000个字节(例如),那么会有一个显着的差异)

此外,我建议您使用std::vector<T>::emplace_back代替std::vector<T>::push_back

std::vector<MYSTRUCT> myvector1;
for (long long i = 0; i < KBIG; i++)
{
    myvector1.emplace_back (1, 1);
}

emplace_back将其参数转发给mystruct的构造函数,因此编译器不会创建无用的副本。