在成员指针变量上具有成员引用变量的原因

时间:2015-04-22 04:23:57

标签: c++

存储对象的引用而不是指针的实际示例和原因是什么?我能想出的明显原因是避免内存管理。

我遇到过一个图书馆,有时一个班级会通过引用存储一个对象,有时候会通过指针存储一个对象,我很难理解为什么以及何时使用一个而不是另一个?

示例:

class EventBusDemo : public Object
{
private:
    HandlerRegistration* playerMoveReg; 
};

class PlayerMoveEvent : public Event
{
private:
    Player& player;  // Why not a pointer here?
};

5 个答案:

答案 0 :(得分:0)

关键点是参考指向的对象的身份不能改变(虽然它的值可以),并且引用不能为空(但如果你不小心,你仍然可以获得悬空引用)

所以如果你看到这样的代码:

class ObjectWithPointer
{
private:
    Object* object; 
};

您可能需要这样做:

void useIt(ObjectWithPointer & value) {
   if(value.object!=NULL) {
      doSomethingWith(*value.object);
   }
}

你也可以这样做:

void modifyIt(ObjectWithPointer & value) {
   value.object!= some_object_ptr;
}

但是如果你有这个:

class ObjectWithRef
{
private:
    Object& object; 
};

第一个例子变成:

void useIt(ObjectWithRef & value) {
   doSomethingWith(value.object);
}

第二次

的天真转换
void modifyIt(ObjectWithRef & value) {
   value.object=some_object;
}

做了一些完全不同的事情 - 它将some_object的值复制到引用中,但是没有办法使引用指向其他地方。

答案 1 :(得分:0)

更好的问题是"为什么要使用指针而不是引用?"。通常,在实际回答此问题时,您应该只使用指针。


为了引用某些东西,指针需要稍微麻烦的语法才能使用。此外,您可以使用指针执行更多操作,而不是使用引用,例如更改它指向的位置,如果您实际上没有执行任何操作,则这是一件坏事。任何看到你指针的精明读者都会被迫考虑各种各样的事情,如果你曾经使用过一个参考资料,就好像你不记得是否记得它,或者想知道你是否改变它的含义。 s指向,等等。

它可能也会损害编译器优化,因为编译器不得不怀疑同样的事情!

答案 2 :(得分:0)

如果您在课程X中看到reference to object而不是指针,X可以认为该对象为local。它位于堆栈中的某个位置。 X无需考虑其毁灭definitely。使用指针,对象将在堆上。程序员(尤其是X的维护者)可能会对谁将释放这个指针感到困惑。因此,参考的安心。比较reference-to-object-on-heappointer-to-object-on-stack时,此点有效。

然后出现了另一个问题,dangling references and dangling pointers

因为,任何人都可以从任何地方调用指针上的删除,很难找到悬空指针的实际原因。不是悬挂参考。因为,当该对象离开堆栈时将被销毁,代码中只有一个位置可以发生(它是创建该对象的位置)。 因此,更容易找到问题。

如果你有一个悬垂的参考,那么设计就会出现问题。在Y中存储对象X的引用时。 X正在使用Y。但是,X的生命周期大于Y。当Y为本地且X为全局时,可能会发生这种情况。这是违反直觉的,因为为什么在堆栈中你会将upper-stack-object的引用存储在lower-stack-object中。 但是对于悬空指针,可能存在错误的逻辑错误或所有权不匹配。因此,如果悬挂参考之类的问题出现,可以通过更好的设计进行修复。

但是,如果我们将对象存储在堆上作为参考,则很难再次找到悬空引用问题。

所以,我的首要任务是:

references to stack object > references to heap object > pointers.

查看你的代码并猜测:EventBusDemo就像一些存储将被调用的注册处理程序的全局总线。这是一个对象,随着时间的推移,你会给它不同的playerMoveReg。所以,它是一个指针。

PlayerMoveEvent看起来很快会被处理,因为它是Event。您将为新事件创建新的PlayerMoveEvent。那么,你想让player指针或引用。您想在事件中更改player(即使是错误的)吗?当然不。你想要一些想法吗?肯定是的。所以,使用参考。

答案 3 :(得分:0)

我认为这几乎总是味道的问题。当您想要强调一个对象不是其他对象的所有者或者您希望避免运行时检查空指针时,可以使用类成员的引用。每种方法都有缺点和优点,但在我的实践中,我避免使用引用作为对象成员,因为你不能重新分配它们的值。

答案 4 :(得分:0)

如果你使用指针,那么:

void PlayerMoveEvent::Foo()
{
  // can it be null? its possible because its a pointer!
  if (player) player->bar(); 
}

PlayerMoveEvent::~PlayerMoveEvent()
{
   // crash? or memory leak with out?
   delete player;
}

引用清楚地表明它对于对象的生命周期(或至少是意图)是有效的,并且您不拥有该对象。除非指针确实需要,否则始终使用引用。