C++:BIG类的性能影响(有很多代码)

问题描述:

我想知道在C++中编写“全能”类是否以及如何实际影响性能。C++:BIG类的性能影响(有很多代码)

如果我有例如,一个类,只有uint x; uint y;作为数据,并且几乎定义了数学可以做到的一切方法。其中一些方法可能很大。 (copy-)构造函数只不过是初始化两个数据成员而已。

class Point 
{ 
    int mx; int my; 
    Point(int x, int y):mx(x),my(y){}; 
    Point(const Point& other):mx(other.x),my(other.y){}; 
// .... HUGE number of methods.... 
}; 

现在。我加载一个大的图像,并创建一个为每个像素,东西em到一个向量和使用他们。 (比方说,所有的方法都会被调用一次) 这只是一个愚蠢的例子!

没有方法但是有很多实用功能,它会比同一个类慢吗?我不是以任何方式谈论虚拟功能!我的动机是:我经常发现自己写了很好的和相对强大的类,但是当我必须像上面例子中那样初始化/使用它们时,我会感到紧张。 我想我不应该。

什么,我认为我所知道的是:

  1. 方法在内存中只有一次存在。 (优化放在一边)
  2. 分配 只发生数据 成员,并且它们是 复制的唯一东西。

所以它应该没关系。我错过了什么吗?

+2

另请参阅:http:// stackoverflow。com/questions/648647/in-c-where-in-memory-are-class-functions-put – 2009-09-15 08:44:03

你说得对,方法只在内存中存在一次,它们就像普通函数一样,隐藏了一个额外的参数。

当然,只有数据成员都采取了在账户分配,那么,继承可能引入一些额外的师生比为vptrs的对象大小,但不是什么大不了的

如果你是真正的担心,你可以告诉你的编译器内联构造函数。这个优化步骤应该为您提供干净的代码和干净的执行。

这些代码2位是相同的:

Point x; 
int l=x.getLength(); 

int l=GetLength(x); 

鉴于类Point具有非虚拟方法的getLength()。第一次调用实际上调用了int getLength(Point &this),与我们在第二个示例中所写的一样,签名相同。 (*)

如果你调用的方法是虚拟的,这当然不适用,因为一切都会经过一个额外的间接级别(类似于C-style int l=x->lpvtbl->getLength(x)),更不用说了对于你实际上有3个像素的每个像素有2个int,额外的一个是指向虚拟表的指针。 (*)这不完全正确,“this”指针是通过一个cpu寄存器而不是通过堆栈传递的,但是这种机制可以很容易地以任何方式工作。

第一:不要过早优化。第二:干净的代码比优化的代码更易于维护。

类的方法有隐藏这个指针,但你不应该担心它。编译器大多数时间都是通过寄存器来传递它。

继承和虚函数在适当的调用中引入了间接指针(继承=构造函数/析构函数调用,虚函数 - 函数的每个函数调用)。

短:你没有创建

  • 对象/破坏往往可以有虚拟方法,继承等等,只要它有利于设计。
  • 您创建/销毁的对象通常应该很小(很少数据成员),并且不应该有很多虚拟方法(最好根本不会 - 性能明智)。
  • 尝试内联小方法/构造函数。这将减少开销。
  • 如果您没有达到预期的性能,请进行干净的设计和重构。

关于具有大或小接口的类有不同的讨论(例如Scott Meyers(More)Effective C++ Books - 他选择最小接口)。但这与表演无关。

+0

认为你的意思不是在你的第二点。同样在第二点中,我认为虚拟方法很少,虚拟调用速度较慢,因此调用大量虚拟方法会产生一些(小)性能问题。 – Elemental 2009-09-15 09:41:45

+0

谢谢 - 当然你是对的。如果你有很少的好处。方法,大多数方法调用都是直接的(对vtbl没有间接的)。如果你设法没有任何好处的课堂。功能,在施工过程中不得设置vtbl。 – 2009-09-15 09:53:50

您已经有了一些相当不错的技术建议。我想抛出一些非技术性的东西:正如STL向我们展示了所有人,在成员函数中执行所有操作可能不是实现此目的的最佳方式。我没有提到争论,而是提到斯科特迈尔斯关于这个问题的类文章:How Non-Member Functions Improve Encapsulation

尽管技术上应该没有问题,但您仍然可能想从设计POV中查看您的设计。

+0

你指出了一篇引人入胜的文章。但我担心的是,这些人的编码似乎与大多数正常人相比差别很大。我喜欢成员函数,因为在每一个值得注意的IDE中,他们都会向我提出并告诉我该类可以做什么。这对于非会员非朋友功能来说并不可行。 – AndreasT 2009-11-11 10:02:34

+0

如果一个免费函数不能告诉你它做了什么,那么它需要一个更好的名字。 – sbi 2009-11-11 13:24:53

+0

不是我的意思。一个IDE提供了类。,它可以减少手册中的慢速查找。免费功能不显示在那里。我可以为他们做一个搜索,但这比键入'更麻烦'。并等待半秒钟。这就是为什么人们只看“坏风格”类的图书馆而没有大量模板魔法和分散界面的原因之一。每个攀登提升掌握高峰的人都可以为自己的成就感到自豪,但只能羡慕图书馆,这些图书馆可以在没有大惊小怪的情况下通过信息进行操作。 – AndreasT 2010-05-25 07:25:56

我创建了与您相同的点类,除了它是模板类并且所有函数都是内联的。我希望看到性能提升不会因此而下降。但是,尺寸为800x600的图像将具有480kpixels,并且其存储器打印将接近4M而没有任何颜色信息。不仅仅是内存,而且初始化480k对象将花费太多时间。因此,我认为这不是一个好主意。但是,如果您使用此类来转换图像的位置,或将其用于图形图元(线条,曲线,圆圈等)

我同意上面的评论wrt:性能和类布局,并且希望添加尚未陈述的关于设计的评论。

对我来说感觉就像你在使用你的Point类超过它的真实设计范围。当然,可以用那种方式,但是应该是呢?

在过去的电脑游戏工作中,我经常遇到类似的情况,通常最好的最终结果是,当进行专门的处理(例如图像处理)时,需要专门的代码集来处理不同的工作输出缓冲区更加高效。

这还允许您以更简洁的方式为重要情况进行性能优化,而不会降低基本代码的可维护性。从理论上讲,我确信使用模板代码,具体类设计等的复杂组合,并获得几乎相同的运行时效率......但我通常并不愿意以实现复杂的实施交易。

我想这是更多的答案不是你要找的,但在这里不用...

SO充满了人们所担心的X,Y或Z的性能问题,那种担心是猜测的一种形式。

如果你担心某件事的表现,别担心,找出

这里是做什么:

  1. 编写程序

  2. Performance tune it

  3. 从经验

这是什么教我学习,我”我一遍又一遍地看到它,是这样的:

  • 最佳实践说不要过早优化

  • 最佳实践说使用大量的数据结构类,具有多层抽象,最好的大型O算法,“信息隐藏”,具有事件驱动和通知式架构。

  • 性能调优揭示其中时间是怎么回事,它是:舞动的通用性,使山出molehills的,调用函数没有实现,他们需要多长时间&性能并且使用指数时间做这在多个层上。

  • 然后问这个问题:大O算法,事件和通知驱动架构等最佳实践背后的原因是什么?答案来了:除其他外,性能

因此,在某种程度上,最好的做法是告诉我们:优化过早。明白这点?它说“不要担心表现”,它说“担心表现”,并且它导致我们试图成功的事情不会成功担心。我们担心的越多,违背我们的判断就越糟糕。

我的建设性建议是:按照上面的步骤1,2和3。这将教你如何使用最佳实践适度,这将给你最好的全面的设计。

成员函数不会与对象一起复制。只有数据字段有助于对象的大小。