这是一个简单的例子来说明问题:
class A {};
class B
{
B(A& a) : a(a) {}
A& a;
};
class C
{
C() : b(a) {}
A a;
B b;
};
所以B
负责更新C
的一部分。 我通过 lint 运行了代码,它抱怨引用成员:lint#1725。
这讨论了如何处理默认复制和赋值,这很公平,但是默认复制和赋值对于指针来说也很糟糕,因此几乎没有什么优势。
我总是尝试尽可能使用引用,因为裸指针不确定谁负责删除该指针。 我更喜欢按值嵌入对象,但如果需要指针,我会使用 std::auto_ptr 作为拥有指针的类的数据成员,并将对象作为引用传递。
当指针可能为空或可能更改时,我通常只会使用指针作为数据成员。 对于数据成员,还有其他原因更喜欢使用指针而不是引用吗?
由于引用一旦初始化就不应更改,因此包含引用的对象不应该是可分配的,这是真的吗?
This is a simplified example to illustrate the question:
class A {};
class B
{
B(A& a) : a(a) {}
A& a;
};
class C
{
C() : b(a) {}
A a;
B b;
};
So B
is responsible for updating a part of C
. I ran the code through lint and it whinged about the reference member: lint#1725.
This talks about taking care over default copy and assignments which is fair enough, but default copy and assignment is also bad with pointers, so there's little advantage there.
I always try to use references where I can since naked pointers introduce uncertaintly about who is responsible for deleting that pointer. I prefer to embed objects by value but if I need a pointer, I use std::auto_ptr
as a data member of the class that owns the pointer, and pass the object around as a reference.
I would generally only use a pointer as a data member when the pointer could be null or could change. Are there any other reasons to prefer pointers over references for data members?
Is it true to say that an object containing a reference should not be assignable, since a reference should not be changed once initialized?
发布评论
评论(9)
我自己的经验法则:
My own rule of thumb :
避免引用成员,因为它们限制类的实现可以执行的操作(包括,正如您提到的,阻止赋值运算符的实现),并且不会为类可以提供的功能提供任何好处。
示例问题:
直到 C++0x,无论如何编辑: C++ 现在有委托构造函数).
运算符等),但行为就像指针(可以悬挂) - 例如 Google 样式指南 不鼓励这样做Avoid reference members, because they restrict what the implementation of a class can do (including, as you mention, preventing the implementation of an assignment operator) and provide no benefits to what the class can provide.
Example problems:
until C++0x, anywayedit: C++ now has delegating constructors).
operator etc), but behaves like a pointer (can dangle) - so e.g. Google Style Guide discourages it对象很少应该允许分配和其他诸如比较之类的东西。 如果您考虑某些具有“部门”、“员工”、“总监”等对象的业务模型,则很难想象将一名员工分配给其他员工的情况。
因此,对于业务对象来说,将一对一和一对多关系描述为引用而不是指针是非常好的。
也许可以将一或零关系描述为指针。
所以没有“我们不能分配”这个因素。
许多程序员只是习惯使用指针,这就是为什么他们会找到任何参数来避免使用引用。
作为成员拥有指针将迫使您或您的团队成员在使用前一次又一次地检查指针,并带有“以防万一”的注释。 如果指针可以为零,那么指针可能会被用作某种标志,这是不好的,因为每个对象都必须发挥自己的作用。
Objects rarely should allow assign and other stuff like comparison. If you consider some business model with objects like 'Department', 'Employee', 'Director', it is hard to imagine a case when one employee will be assigned to other.
So for business objects it is very good to describe one-to-one and one-to-many relationships as references and not pointers.
And probably it is OK to describe one-or-zero relationship as a pointer.
So no 'we can't assign' then factor.
A lot of programmers just get used with pointers and that's why they will find any argument to avoid use of reference.
Having a pointer as a member will force you or member of your team to check the pointer again and again before use, with "just in case" comment. If a pointer can be zero then pointer probably is used as kind of flag, which is bad, as every object have to play its own role.
可以时使用引用,必要时使用指针。
Use references when you can, and pointers when you have to.
在一些重要的情况下,根本不需要可分配性。 这些通常是轻量级算法包装器,可以在不离开范围的情况下方便计算。 此类对象是引用成员的主要候选者,因为您可以确保它们始终持有有效引用并且永远不需要复制。
在这种情况下,请确保使赋值运算符(通常还有复制构造函数)不可用(通过继承
boost::noncopyable
或将其声明为私有)。然而,正如用户 pts 已经评论的那样,对于大多数其他对象来说情况并非如此。 在这里,使用引用成员可能是一个大问题,通常应该避免。
In a few important cases, assignability is simply not needed. These are often lightweight algorithm wrappers that facilitate calculation without leaving the scope. Such objects are prime candidates for reference members since you can be sure that they always hold a valid reference and never need to be copied.
In such cases, make sure to make the assignment operator (and often also the copy constructor) non-usable (by inheriting from
boost::noncopyable
or declaring them private).However, as user pts already commented, the same is not true for most other objects. Here, using reference members can be a huge problem and should generally be avoided.
由于每个人似乎都在发布一般规则,我将提供两条:
永远不要使用引用作为类成员。 我从未在自己的代码中这样做过(除了向自己证明我在这条规则中是正确的),并且无法想象我会这样做的情况。 语义太混乱了,而且这确实不是引用的设计目的。
在向函数传递参数时,始终始终使用引用(基本类型除外),或者当算法需要副本时。
在向
这些规则很简单,对我很有帮助。 我将有关使用智能指针(但请不要使用 auto_ptr)作为类成员的规则留给其他人。
As everyone seems to be handing out general rules, I'll offer two:
Never, ever use use references as class members. I have never done so in my own code (except to prove to myself that I was right in this rule) and cannot imagine a case where I would do so. The semantics are too confusing, and it's really not what references were designed for.
Always, always, use references when passing parameters to functions, except for the basic types, or when the algorithm requires a copy.
These rules are simple, and have stood me in good stead. I leave making rules on using smart pointers (but please, not auto_ptr) as class members to others.
是的:是否可以说包含引用的对象不应分配,因为引用一旦初始化就不应更改?
我对数据成员的经验法则:
Yes to: Is it true to say that an object containing a reference should not be assignable, since a reference should not be changed once initialised?
My rules of thumb for data members:
是的。 代码的可读性。 指针更明显地表明该成员是一个引用(讽刺的是:)),而不是一个包含的对象,因为当您使用它时,您必须取消引用它。 我知道有些人认为这已经过时了,但我仍然认为它只是为了防止混乱和错误。
Yes. Readability of your code. A pointer makes it more obvious that the member is a reference (ironically :)), and not a contained object, because when you use it you have to de-reference it. I know some people think that is old fashioned, but I still think that it simply prevent confusion and mistakes.
我建议不要引用数据成员,因为您永远不知道谁将从您的类中派生以及他们可能想要做什么。 他们可能不想使用引用的对象,但作为引用,您迫使他们提供有效的对象。
我已经对自己做了足够多的事情以停止使用参考数据成员。
I advise against reference data members becasue you never know who is going to derive from your class and what they might want to do. They might not want to make use of the referenced object, but being a reference you have forced them to provide a valid object.
I've done this to myself enough to stop using reference data members.