什么时候对象足够大,以至于通过引用而不是通过值传递可以获得性能增益



正如Charles Bailey在这个问题中所回答的,当对象类型较大时应该考虑通过常量引用传递,但是什么样的对象被认为是大的呢?

编辑:

为了提供更多的数据,可以用来提供一个更具体的答案,我决定在这个描述中添加一个现实世界的问题。

假设我们有一个这样的对象:

typedef struct dipl {
    quint16 __id;
    quint16 __pos;
    quint16 __len;
} data;

我们还有一个这样的对象:

class bidipl
{
public:
    bidipl();
    quint8 id();
    void setid(quint8 __id);
    void appenddipl(dipl __dipl);
private:
    qint8 _M_id;
    dipllist _M_dipllist;
};

其中dipllisttypedef QList<dipl> dipllist;。对象diplbidipl创建一次,但访问可能超过100次一分钟。那么我们应该如何将dipl传递给我们的append函数呢?

void appenddipl(dipl __dipl);

void appenddipl(const dipl& __dipl);

按值传递对象有两个单独的成本:复制数据表示和执行构造函数。你需要考虑两者的成本。

  • 复制数据通常很快,但要保持在合理范围内。按值传递struct { int[7]; }是可以的,但对于struct { int[20000]; }可能不是那么多。

  • 执行构造函数可能会执行动态分配,这会带来异常风险和同步成本。这可能是微不足道的,也可能是重要的。这取决于.

应该无条件传递值的变量只有那些单词大小的内置类型。

什么应该被认为足够大,以证明通过引用而不是按值传递?你会发现不同的答案:

  • 任何大于处理器上的自然数据类型(x86上32位,x86-64位):这里甚至std::pair<int, int>都应该通过引用传递。

  • 数据保存到动态内存位置的容器(例如vectors, strings)

我个人的品味是:原始数据按值,结构按引用。

通过分析特定架构上的特定应用程序,您将找到唯一有效的答案。如果没有实际的分析,任何关于性能的讨论都是徒劳的

正如Charles所说,当所讨论的值的大小等于或小于对象引用的大小时,只传递值而不传递引用会明显提高性能。然而,由于访问值可能需要解引用操作,这取决于上下文的细节和编译器的"智能"程度,因此传递大小略大于引用的值仍然可能是"值得的"。然而,这已经开始鸡毛蒜皮了,而且很少有意义。

任何非基本类型的对象,包括任何类对象、结构体或容器

最新更新