GCC优化std :: tie仅用于可读性吗?

syn*_*gma 6 c++ optimization tuples tie c++11

假设我有一个std::tuple:

std::tuple<int,int,int,int> t = {1,2,3,4};
Run Code Online (Sandbox Code Playgroud)

我想std::tie仅仅为了可读性目的而使用:

int a, b, c, d; // in real context these names would be meaningful
std::tie(a, b, c, d) = t;
Run Code Online (Sandbox Code Playgroud)

与仅使用t.get<int>(0)

GCC会优化这个元组的内存使用还是会为a, b, c, d变量分配额外的空间?

Sha*_*our 7

在这种情况下,我没有看到任何原因,在as-if规则下,编译器只需要模拟程序的可观察行为.使用godbolt的快速实验:

#include <tuple>
#include <cstdio>

void func( int x1, int x2,int  x3, int x4)
{
  std::tuple<int,int,int,int> t{x1,x2,x3,x4};

  int a, b, c, d; // in real context these names would be meaningful
  std::tie(a, b, c, d) = t;

  printf( "%d %d %d %d\n", a, b, c, d ) ;
}
Run Code Online (Sandbox Code Playgroud)

表明gcc确实优化了它:

func(int, int, int, int):
    movl    %ecx, %r8d
    xorl    %eax, %eax
    movl    %edx, %ecx
    movl    %esi, %edx
    movl    %edi, %esi
    movl    $.LC0, %edi
    jmp printf
Run Code Online (Sandbox Code Playgroud)

另一方面,如果你使用了一个地址t并将其打印出来,我们现在有了可观察的行为,它依赖于t现有的(见它的实时):

printf( "%p\n", static_cast<void*>(&t) );
Run Code Online (Sandbox Code Playgroud)

我们可以看到gcc不再优化t:

movl    %esi, 12(%rsp)
leaq    16(%rsp), %rsi
movd    12(%rsp), %xmm1
movl    %edi, 12(%rsp)
movl    $.LC0, %edi
movd    12(%rsp), %xmm2
movl    %ecx, 12(%rsp)
movd    12(%rsp), %xmm0
movl    %edx, 12(%rsp)
movd    12(%rsp), %xmm3
punpckldq   %xmm2, %xmm1
punpckldq   %xmm3, %xmm0
punpcklqdq  %xmm1, %xmm0
Run Code Online (Sandbox Code Playgroud)

在一天结束时,您需要查看编译器生成的内容并分析您的代码,在更复杂的情况下,它可能会让您大吃一惊.仅仅因为允许编译器进行某些优化并不意味着它会.我已经看过更复杂的情况,编译器没有按照我的预期进行操作std::tuple.godbolt在这里是一个非常有用的工具,我无法计算我曾经通过将简单的例子插入godbolt而被颠覆了多少优化假设.

注意,我通常printf在这些示例中使用,因为iostreams会生成大量代码,这些代码会妨碍示例.