小型简单结构是否应该通过 const 引用传递?
我一直被教导非原始类型应该尽可能通过 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 版本?
是这样吗?简单对象最好按值传递吗?这条线应该划在哪里?
I have always been taught that non-primitive types should be passed by const reference rather than by value where possible, ie:
void foo(std::string str);//bad
void foo(const std::string &str);//good
But I was thinking today that maybe actually some simple user defined types may actually be better passed by value eg:
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?
My thought is that by passing the Vector2 by reference, it is actually more expensive than passing by value since the compiler is now using a pointer and dereferencing to access the const Vector2 &pos version?
Is this the case? Are simple objects best off passed by value? Where should the line be drawn?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
如果您传递一个对象,其中 <代码>size_of(object) < size_of(指向对象的指针)。例如,
char const&
可能比char
更昂贵It would be true if you passed an object where
size_of(object) < size_of(pointer_to_object)
. For example,char const&
might be more expensive thanchar
是的,简单的对象应该按值传递。这条线必须根据架构来绘制。如有疑问,请进行简介。
Yes, simple objects should be passed by value. The line has to be drawn according to the architecture. If in doubt, profile.
正如策略问题一样,我通过 const 引用传递任何不是基本 C 数据类型的对象。这样更容易记住。
Just as a matter of policy I pass any object that isn't a basic C data type by const reference. Its much easier to remember that way.
通过 const 引用传递可以避免构造新对象。如果你的构造函数很重要,例如,它分配内存,那么通过 const 引用传递比通过值传递要得多。
在 C# 世界中,您可以通过选择将某些内容设为类还是结构来做出此决定。类使用引用语义,而结构使用值语义。我读过的所有内容都表明,您通常应该选择将所有内容都作为一个类,除非它非常小,即大约 16 字节。如果您正在寻找 C++ 中何时按值传递与 const 引用传递的界限,16 字节似乎是一个合理的阈值。
Passing by const reference avoids the construction of a new object. If your constructor is non-trivial, e.g., it allocates memory, you will be much better off passing by const reference than by value.
In the C# world, you make this decision by choosing whether to make something a class or a struct. Classes use reference semantics while structs use value semantics. Everything I've ever read says that you should generally choose to make everything a class unless it is very small, i.e., on the order of 16 bytes. If you are looking for a cut-off for when to pass by value versus const reference in C++, 16 bytes seems like a reasonable threshold.
我没有看到提及的一个因素是例程将如何处理传入的值。除非例程内联扩展,否则操作按引用传递的数据将比操作按值传递的数据需要更多代码。如果传入结构的字段平均访问次数少于一次,则与复制结构的开销相比,这种额外开销将会很小。如果它们平均每个都会被访问多次,那么将它们放在堆栈上可能会更好。如果接口已经设置为频繁访问的结构的引用传递,则被调用的例程复制所有感兴趣的部分可能是有意义的。另一方面,如果被调用的例程无论如何都要复制大部分或全部结构,那么它也可以按值传递。
One factor I've not seen mentioned is what the routine is going to do with the passed-in value. Unless the routine is expanded inline, manipulating data which are passed by reference will require more code than manipulating data which are passed by value. If the fields of the passed-in structure will on average be accessed less than once each, this extra overhead will be small compared with the overhead of copying the structure. If they will on average be accessed many times each, it would likely be better to have them on the stack. If the interface is already set as pass-by-reference for a structure which is heavily accessed, it may make sense for the called routine to copy all parts that are of interest. On the other hand, if the called routine is going to copy much or all of a structure anyway, it may as well be passed by value.
可以在 http://www 找到对传递参数的详细信息的较旧但清晰的分析。 .ddj.com/184403855。当然,c++0x 通过移动语义消除了很多此类问题,但是本文提供了很多理由来说明为什么需要移动语义。
An older, yet lucid, analysis of the ins-n-outs of passing parameters can be found at http://www.ddj.com/184403855. Of course c++0x obviates a lot of such issues with move semantics, but the paper provides a lot of justification for why move semantics are desirable.