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

标签 c++ c++17 stdtuple

我在各种情况下使用 std::tuple 并发现了一些有效的方法,但我不确定它们是否会降低性能。

在 C++17 中,为 ifswitch 语句引入了 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) xy 在编译时解析,而不是在运行时解析,因此这似乎是一个没有大的运行时损失的解决方案,不是吗? 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。实际上也没有提到元组或条件分支。

这是“仿佛”规则所允许的。

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

关于c++ - init 语句中临时 std::tuple 的开销,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50454170/

相关文章:

c++ - std::get<0>(...) 和枚举索引

c++ - 如何为 C++ 元组编写折叠/求和函数?

c++ - 使用分配器 C++ 创建元组

c++ - 为什么使用 _Bool 和 bool 而不是 int8_t 或 char?

c++ - libjpeg 中的指针对齐

c++ - 类模板如何存储引用或值?

c++ - 在 C++17 中排序的移位操作数

c++ - 类数据成员中可以使用模板参数推导吗?

c++ - openssl libcrypto.a 和 libmysqlclient.a 关于 `ERR_remove_thread_state' 的多重定义

c++ - OpenGL 3.3 没有渲染纹理(黑色纹理、C++、GLFW/SOIL)