我在各种情况下使用 std::tuple
并发现了一些有效的方法,但我不确定它们是否会降低性能。
在 C++17 中,为 if
和 switch
语句引入了 init 语句。为了定义多个不同类型的变量,您可以使用临时元组和结构化绑定(bind)。
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;
}
这不应该有很大的性能损失(如果有的话)。当然,它会创建一个元组,它本身比类型本身需要更多的内存,但这是在堆栈上分配的,所以同样,它不应该真正造成太大的伤害。绑定(bind) x
和 y
在编译时解析,而不是在运行时解析,因此这似乎是一个没有大的运行时损失的解决方案,不是吗? p>
编辑:更新了示例以防止编译器简单地优化元组并使问题更加清晰。
最佳答案
在给定的示例中,编译器证明不分配给 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。实际上也没有提到元组或条件分支。
这是“仿佛”规则所允许的。
关于c++ - init 语句中临时 std::tuple 的开销,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50454170/