init语句中临时std :: tuple的开销

时间:2018-05-21 17:50:23

标签: c++ c++17 stdtuple

我在各种环境中玩std::tuple并遇到了一些有用的东西,但我不确定它们是否会有性能损失。

在C ++ 17中,为ifswitch语句引入了一个init语句。为了定义不同类型的多个变量,可以使用临时元组和结构化绑定。

if(const auto& [x, y] = std::tuple{some_expensive_int_calculation(), get_string_message()}; x != 0 && y != "") {
    std::cout << "X is " << x << ", message equals " << y << std::endl;
}

当然它会创建一个元组,它本身需要比类型本身更多的内存,但这是在堆栈上分配的,所以再次,它不应该真的伤害那么多。绑定xy在编译时解决,而不是在运行时解决,因此这似乎是一个没有大运行时惩罚的解决方案,是吗?

编辑:更新了示例,以防止编译器琐碎地优化元组并使问题更加清晰。

1 个答案:

答案 0 :(得分:3)

在给定的示例中,编译器证明不为x分配或分配存储与分配和测试x具有相同的结果是相当简单的。因此,在启用优化的情况下,我希望它不会在生成的汇编程序中提及x

确实,使用gcc 7.3 -O2,以下程序:

#include <tuple>
#include <iostream>

int main()
{
    if(const auto& [x, y] = std::tuple{0, "Test"}; x == 0) {
        std::cout << y << std::endl;
    }
}

变为:

main:
# stack-frame related code
  sub rsp, 8
# get address of "Test" string
  mov esi, OFFSET FLAT:.LC0
# get address of std::cout
  mov edi, OFFSET FLAT:std::cout
# call operator <<
  call std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)
# move returned ostream reference to rdi (arg1)
  mov rdi, rax
# and call std::endl
  call std::basic_ostream<char, std::char_traits<char> >& std::endl<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&)
# return 0
  xor eax, eax
# clean up stack and return
  add rsp, 8
  ret

请注意,此汇编器输出中的任何位置都没有提及x。也确实没有提到元组或条件分支。

“似乎”规则允许这样做。

http://en.cppreference.com/w/cpp/language/as_if