将int包装在类中会有任何性能惩罚吗?

13

我有一个项目,其中包含许多向量、集合和映射。在大多数情况下,键/索引是整数。我正在考虑创建像这样的小类:

class PhoneRepoIx //index into map {phone_number => pointer}
{
public:
  int n;
};

class PersonIx //index into map {social_security_number => pointer}
{
public:
  int n;
};

如果我这样做,会有速度或内存损失吗?关于内存,我90%确定每个实例不会有内存成本,只有每个类类型。关于速度,我不太清楚。

动机: 采用上述方法,编译器将为我执行一些额外的类型检查。此外,使用选择得当的显式类型名称,我的代码读者将更容易看出我在做什么。目前,我在所有地方都使用int,并选择变量名称来表达每个索引的含义。而采用上述方法,我的变量名称可以更短。

注意: 类型定义并不能完全解决我的问题,因为编译器不会执行任何额外的类型检查,在内部所有类型都将是int。


1
编写 struct PersonIx { int n; } 更短,完全相同,也不需要任何 typedef。我认为除了在代码使用类型时由于包装器而人为地使其不够优化之外,也不会有任何开销。 - fork0
1
"Tyepdefs并不能完全解决我的问题,因为编译器不会进行任何额外的类型检查,内部所有类型都只是int。这到底是什么意思?你认为需要哪些“额外的类型检查”?在这里我们需要使用一个用法示例。" - Falmarri
2
@Falmarri: “你之前的订单多出了5个。”这里的“5”指的是数量、包裹重量、支付金额还是支付日期呢? - Ben Voigt
2
不要理会那些无知的反对者。这是一个好方法。 - Konrad Rudolph
2
@BenVoigt 我认为这不是重复的,有三个原因:1)即使那里的一些答案很好,但另一个问题的被接受答案很糟糕。2)这个问题特别询问性能影响。3)“重复”实际上是关于C语言的(这解释了被接受的答案)。 - Konrad Rudolph
显示剩余7条评论
3个回答

7

不同的编译器有不同的优化能力和不同的错误。理论上可以精确地进行零开销编译。你的编译器会达到这个理论极限吗?答案是肯定的“可能”。至少有些编译器已经在某些时候做到了。

更有趣的问题是,您是否应该担心可能的性能降低。对于这个问题的答案是强烈的“不”。除非您的程序确实表现出不可接受的性能指标。


9
这个回答大大低估了现代编译器的能力。我希望一个不错的编译器可以把这段代码优化到零开销。事实上,有几个库(其中包括C++标准库的一部分)需要编译器这样做,否则它们会遭受巨大的性能损失。总的来说,答案不是“可能”,而是“是”,或者“更换你的编译器”。 - Konrad Rudolph
2
@KonradRudolph:我曾多次比较过g++为裸类型和包装类型生成的汇编代码。大多数情况下没有任何开销,但并非总是如此。在这方面,clang++要稍差于g++。 - n. m.

4
我建议使用模板来实现您想要的功能。
template <typename T>
struct Index {
    Index(int value) : value(value) {}
    int value;
};

这是用法。

struct PhoneRepoIx {};
Index<PhoneRepoIx> PhoneIndex(1);
list[PhoneIndex.value];

4
这个类通常会调用两个函数:
  • 构造函数
  • operator<(由于STL map是一种树实现,因此键应支持此功能)
我认为上面的答案“不要担心”听起来很好(先优化再调整)。但是为什么这不会导致任何减速(猜测):
  • 构造函数:一个好的编译器可以将其转换为堆栈指针增量(为int腾出空间),然后设置可用空间。
  • operator<:一个好的编译器可以内联两个对象的'n'之间简单的比较。

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