我知道std::tuple
是从函数返回不同类型的多个变量的有效方法,如a talk by Herb Sutter中大约1:31:00所述(此代码示例是我的,不是来自视频)
auto get_tuple()
{
return std::make_tuple(1, 2);
}
然后用
“解包”它auto t = get_tuple();
int a = std::get<0>(t);
int b = std::get<1>(t);
或
int a;
int b;
std::tie(a, b) = get_tuple();
这些方法很棒,但我并不特别喜欢语法std::get
或std::tie
。我不会因为语法难以使用而使用有用的工具(在我个人看来),但是这样做呢?
auto get_struct()
{
struct R
{
int a;
int b;
}
return R{1, 2};
}
这为我编译(Visual Studio 2015),我更喜欢它的语法。我不想被指责过早优化,但我也会提到它似乎比元组快很多倍。大多数情况下,我只是喜欢语法。
那就是说,我知道这只是因为编译的东西并不意味着语言就是这样使用的。我不确定如何说出这个问题,但基本上,这是有效和定义的行为吗?我是否可以确信这将适用于其他主要编译器?坦率地说,即使在函数本身中定义了该类型,它也会推断它会推断出类型,所以我想确保它没问题。
这是我第一次在这个网站上发帖,如果我做错了,请提前抱歉。如果我这样做,请告诉我。
编辑:正如在回复中指出的那样,我声称本地结构比元组快几倍是完全错误的。我没有正确地进行测试。请参阅回复了解更多内容,我只是想编辑它以确保我不会误导任何人。答案 0 :(得分:4)
虽然本地结构符合标准,但我建议不要使用它(而不是元组)。首先,绩效指标可能不正确。
以下代码:
#include <tuple>
auto get_tuple()
{
auto tup = std::make_tuple(1.0f, 2.0f);
return tup;
}
auto get_struct() {
struct R {
float a, b;
};
return R{1, 2};
}
以优化模式生成以下ASM:
get_tuple():
movq %rdi, %rax
movl $0x40000000, (%rdi)
movl $0x3f800000, 4(%rdi)
ret
get_struct():
movq .LC3(%rip), %xmm0
ret
.LC3:
.quad 4611686019492741120
因此只有两个movl
指令更长。我不认为衡量这种效果是否可行。
而元组只是提供了比结构更多的东西!您可以根据元素(编译时)了解它的大小。您可以连接元组。您可以在它们上构建一个反射系统。您可以将它们与std::tie
一起使用。您可以提供他们的类型。 (使用本地结构,它将自动一直向下)。当地的结构没有这样的东西。
答案 1 :(得分:3)
[...]这是有效且定义的行为吗?
是的,您可以声明一个本地类并返回它的实例。那很好。
我不想被指责过早优化,但我也会提到它似乎比元组快很多倍。
我怀疑运行时性能应该是由两个int
和std::tuple<int, int>
组成的本地结构之间的任何不同。编译时,确定tuple
会慢一些。
因为一旦你返回一个本地类的实例,它不是真的本地,你可以把它变成一个非本地类:
struct R { ... };
R get_struct();
然后,关于这是否有效的问题甚至更少。
此外,您可以随时直接将元组输出插入解压缩的内容。查看Yakk's answer之类的内容:
std::tuple<int, int> get_tuple();
unpack(get_tuple(), [](int i, int j) { ... });
get_tuple() *then* [](int i, int j){ ... };
您可能也很高兴知道有一个structured bindings proposal可以直接允许:
auto {a, b} = get_tuple();
答案 2 :(得分:1)
这是有效的行为,你说它比使用元组更快是正确的。但是,您使用的是内置类型的简单案例。使用std::tuple
和struct
与用户定义类型的性能差异可能会使std::tuple
更具吸引力,尽管语法不太优雅。