是否应该通过 const 引用传递小的简单结构?

Posted

技术标签:

【中文标题】是否应该通过 const 引用传递小的简单结构?【英文标题】:Should small simple structs be passed by const reference? 【发布时间】:2011-03-19 20:17:39 【问题描述】:

我一直被教导非原始类型应该通过 const 引用而不是在可能的情况下通过值传递,即:

void foo(std::string str);//bad
void foo(const std::string &str);//good

但我今天在想,也许实际上一些简单的用户定义类型实际上可能更好地按值传递,例如:

class Vector2

public:
    float x, y;
    ...constructors, operators overloads, utility methods, etc...
;

void foo(Vector2 pos);
void foo(const Vector2 &pos);//is this really better than by value?
void foo(float x, float y);//after all isn't by value effectively doing this?

我的想法是,通过引用传递 Vector2,实际上比通过值传递更昂贵,因为编译器现在使用指针和取消引用来访问 const Vector2 &pos 版本?

是这样吗?简单的对象最好按值传递吗?应该在哪里画线?

【问题讨论】:

请注意,如果您的类类型有用户声明的构造函数,则它不是 POD。 一般经验法则:通过 const-reference 传递,除非 sizeof(T) <= sizeof(void*)T 是原始的。 @GMan,你打败了我(和 +1)。虽然,我会概括为它可能小于或等于处理器的字长。而且,应该检查处理器规格以找出最佳尺寸。如果我没记错的话,在某些情况下,无论大小如何,编译器都可能将 const ref 优化为按值传递。考虑到新的移动语义,我想这在 C++0x 中尤其如此。 @James 我想不符合当前的 C++03 标准,尽管从外观上看 C++0x 会认为这是一个 POD。 我认为在极少数情况下您的对象会小于处理器的字长和/或 sizeof(void*) ... @Fire 你真的需要画一个非常薄的行;-) 【参考方案1】:

是的,简单的对象应该按值传递。必须根据架构绘制线。如有疑问,请提供个人资料。

【讨论】:

【参考方案2】:

作为一项政策,我通过 const 引用传递任何不是基本 C 数据类型的对象。这样更容易记住。

【讨论】:

【参考方案3】:

通过 const 引用传递避免了新对象的构造。如果您的构造函数不平凡,例如,它分配内存,那么通过 const 引用传递比通过值传递会很多更好。

在 C# 世界中,您可以通过选择将某物设为类还是结构来做出此决定。类使用引用语义,而结构使用值语义。我读过的所有内容都表明,您通常应该选择将所有内容都设为类,除非它非常小,即大约 16 个字节。如果您正在寻找 C++ 中值传递与 const 引用传递的截止时间,16 字节似乎是一个合理的阈值。

【讨论】:

POD 类型没有重要的复制构造函数(或者实际上也没有重要的默认构造函数或析构函数)。 OP 没有明确说 POD 类型。他说simple用户定义类型,然后举了一个例子表明它有一个构造函数。【参考方案4】:

可以在http://www.ddj.com/184403855 找到对传递参数的 ins-n-outs 的较旧但清晰的分析。当然,c++0x 避免了很多关于移动语义的此类问题,但是这篇论文为为什么需要移动语义提供了很多理由。

【讨论】:

【参考方案5】:

我没有看到提到的一个因素是例程将如何处理传入的值。除非该例程是内联扩展的,否则操作通过引用传递的数据将需要比操作通过值传递的数据更多的代码。如果传入结构的字段平均每个访问不到一次,那么与复制结构的开销相比,这个额外的开销将很小。如果它们平均每个都会被访问多次,那么将它们放在堆栈上可能会更好。如果接口已经被设置为一个频繁访问的结构的传递引用,那么被调用的例程复制所有感兴趣的部分可能是有意义的。另一方面,如果被调用的例程无论如何都要复制大部分或全部结构,那么它也可以按值传递。

【讨论】:

【参考方案6】:

我的想法是,通过引用传递 Vector2,实际上比通过值传递更昂贵,因为编译器现在使用指针和取消引用来访问 const Vector2 &pos 版本

如果你传递了一个 size_of(object) < size_of(pointer_to_object) 的对象,那将是真的。例如,char const& 可能比 char 更昂贵

【讨论】:

如果重复取消引用将导致比不传递尽可能多的数据所节省的开销更多,这也可能是真的。或者,如果引用由于混叠问题而阻止优化。或者,如果引用会伤害您所在的地区。

以上是关于是否应该通过 const 引用传递小的简单结构?的主要内容,如果未能解决你的问题,请参考以下文章

复制赋值运算符应该通过 const 引用还是按值传递?

为啥向量被视为按值传递,即使它是通过 const 引用传递的?

C++ 通过常量引用传递和通过常量引用返回

在 C++ 中,通过引用传递 const long double 是不是很好?

C++ 和 QT4.5 - 传递 const int& 过大?通过引用传递是不是有助于信号/插槽?

通过 const 引用传递对象?