正如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;
};
其中dipllist
为typedef QList<dipl> dipllist;
。对象dipl
和bidipl
创建一次,但访问可能超过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所说,当所讨论的值的大小等于或小于对象引用的大小时,只传递值而不传递引用会明显提高性能。然而,由于访问值可能需要解引用操作,这取决于上下文的细节和编译器的"智能"程度,因此传递大小略大于引用的值仍然可能是"值得的"。然而,这已经开始鸡毛蒜皮了,而且很少有意义。
任何非基本类型的对象,包括任何类对象、结构体或容器