具有2个单元格的结构体与std::pair有何区别?

35

可能是重复问题:
使用具有两个字段的结构体和成对比较有什么区别?

大家好,

我有一个小问题,关于pairs和struct。使用std::pair是否比使用具有两个字段的结构体有任何优势? 我已经用了一段时间的pairs,但主要问题是可读性: 例如,如果您想表示一个二元组(int“label”,double“value”),则可以使用以下方式之一:

typedef std::pair<int,double> myElem;
或者一个。
typedef struct {
    int label;
    double value;
} myElem;

如果你的语句具有“语义”意义,代码会变得更易读(你总是知道x.label是什么,而x.first不是这种情况)。

然而,我想使用pair可能有一些优势。它是否更高效或有其他好处?


@KennyTM:是的,抱歉。我在搜索时错过了这个主题。 - ThR37
5个回答

33

就性能而言:这很可能不会改变什么,你只是在美化它。

就可用性而言,我宁愿使用自定义结构体,可以这样声明(顺便说一下):

struct MyElement
{
  int label;
  double value;
};

我坚定支持强类型,并且当它不仅仅是暂时的东西时,我更喜欢使用“真正”的结构(最好是类),而不是临时元组。

主要是因为:

  • 如你所述,firstsecond并没有太多意义
  • 你无法向std::pair添加方法或其他字段
  • 你无法向std::pair添加类不变量

总之,我认为使用一个专门的定制结构比一个一刀切的元组对维护有益。


9
一个pair被实现为一个模板化的struct。它为您提供了一种创建(通常是异构的)对的简写方式。此外,有一些类型约束限制您可以与pair一起使用的类型:

类型要求

T1和T2必须都是可赋值的模型。其他操作还有其他要求。只有在T1和T2都是默认可构造的情况下才能使用Pair的默认构造函数,只有在T1和T2都是相等可比较的情况下才能使用operator==,只有在T1和T2都是小于可比较的情况下才能使用operator<。

(来自SGI STL std::pair文档)
如果类型不遵循这些约束或者您不关心这些约束,则定义自己的POD可能是有意义的。
最后,我猜这是个人选择/编码风格问题。

7
它的主要优点是通用性。例如,当您从std::map中检索某些内容时,您将在std::pair的第一和第二项中获取键和相关值。
同样,当您使用std::equal_range在集合中查找一组相等的值时,您将在std::pair的第一和第二项中获得范围的开始和结束迭代器。
很难想象适用于这两者的有意义的标签,因此他们选择了一些不太有意义但至少不会误导的标签。对于std::map,使用“key”和“data”可能有效,但对于std::equal_range则会产生误导(如果您切换到类似于lower_boundupper_bound之类的内容以使它们更有意义,则对于std::map中的项目同样错误)。

6
仅代表个人意见,但我不喜欢他们所做的选择。一个映射条目应该是(键,值),而一个范围应该是(开始,结束)。现在,我们被迫在两种情况下使用毫无意义且误导性的(第一,第二)。而且更改字段名称很困难,也不符合惯用语言。 - stefaanv

6
然而,我认为使用pair有一个优点。它是否更高效或其他原因呢?
我怀疑这一点,实例化的std::pair只是一个struct。虽然std::pair带有定义的operator<,但对于仅具有两个成员的结构来说,自己完成这个操作并不太难。
因此,我通常像你推理的那样:具有专用成员名称的struct比first和second更易读。

4

使用std::pair,您可以自由地使用STL中的functors,例如select1st或select2nd。同样,它允许您与您的pair一起使用其他通用函数,例如operator<和其他函数。不可否认的是,随着boost/tr1的出现,您可以通过使用bind来实现类似的效果。

尽管如此,您提到的可读性问题非常真实。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接