【发布时间】:2011-10-04 22:50:54
【问题描述】:
std::pair 和只有两个成员的std::tuple 之间有区别吗? (除了std::pair 需要两个而且只有两个成员,tuple 可能有更多或更少......)
【问题讨论】:
标签: c++ visual-studio-2010 tuples std-pair stdtuple
std::pair 和只有两个成员的std::tuple 之间有区别吗? (除了std::pair 需要两个而且只有两个成员,tuple 可能有更多或更少......)
【问题讨论】:
标签: c++ visual-studio-2010 tuples std-pair stdtuple
有一些区别:
标准并不要求std::tuple 永远是standard-layout。如果T 和Y 都是标准布局,则每个std::pair<T, Y> 都是标准布局。
获取pair 的内容比获取tuple 的内容要容易一些。你必须在tuple 的情况下使用函数调用,而pair 的情况只是一个成员字段。
但仅此而已。
【讨论】:
.first 和.second 很方便,但如果代码更改需要第三个(或更多)成员,它们也无济于事。我注意到我倾向于使用std::get,无论在任何Getter中,我都不需要更改所有内容,只需更改数据类型和任何make_pair调用make_tuple调用。
tuple 成为标准布局?
std::tuple 的名称较长(多出一个字符)。更多这些字符是用右手输入的,因此对大多数人来说更容易输入。
也就是说,std::pair 只能有两个值 - 不能是零、一、三或更多。两个值。然而,元组对值的数量几乎没有语义限制。因此,std::pair 是一种更准确、类型安全的类型,可以在您实际想要指定一对值时使用。
【讨论】:
std::tuple<> 是也是类型安全的(怎么可能不是?),2 在语义上与pair 没有区别。跨度>
这是一个非常晚的答案,但请注意,由于std::pair 是使用成员变量定义的,因此无法使用empty base class optimization 优化其大小(first 和second 必须占用不同的地址,即使其中一个或两个都占用是一个空类)。 second_type 的任何对齐要求都会加剧这种情况,因此在最坏的情况下,生成的 std::pair 基本上会是所需大小的两倍。
std::tuple 仅允许通过辅助函数进行访问,因此如果其中一个为空,则它可以从任一类型派生,从而节省开销。至少,GCC 的实现肯定是这样做的……您可以通过标头来验证这一点,但也有 this 作为证据。
【讨论】:
[[no_unique_address]]应该消除std::pair的劣势。
T,它是空的并且可以简单地复制。最后一个意味着可以从另一个现有的T 转到memcpy。这将复制一个字节,因为空类型的大小为 1。如果您有 tuple<T, int>,如果您获得对 T 的引用,则可以在其上复制一个字节。如果tuple 优化了T 的存储空间,那么它无疑会与int 重叠。因此,复制该字节部分复制了int,从而破坏了它。
memcpy 的规则中有明确的规定:如果对象是基类就不行类子对象(注意:这在 C++20 中扩展为 no_unique_address 成员子对象)。 tuple 的成员没有这样的例外。
请注意,在 C++ 17 中,可以使用相同的接口从具有两个元素的对和元组中读取数据。
auto [a, b] = FunctionToReturnPairOrTuple();
无需使用get<> :)
【讨论】:
不管怎样,我发现 std::tuple 的 GDB 输出更难阅读。显然,如果您需要 2 个以上的值,则 std::pair 将不起作用,但我确实认为这是支持结构的一点。
【讨论】:
std::get<0>(tupleName) 包装在一个吸气剂中; GetX() 更容易阅读且更短。它有一个小缺点,如果您忘记将其设置为 const 方法,有人可能会做一些愚蠢的事情:GetX() = 20;。
也许值得注意的是,cppreference 指出:
“一对是具有两个元素的 std::tuple 的特定情况。”
【讨论】:
std::pair's change history 提问时没有出现此文字。历史上最早出现的文字是two years later