1

C++

Is it better to update the value of a pointer or to change the pointer to point to something else?

Let's say we have two classes: ball and coordinates.

class ball
{
    Coordinates *ballCurrent;
    public:
        ball(int);
        ~ball();
        void setLoc(Coordinates&); // OR void setLoc(int, int);
};

class Coordinates
{
    int x, y;
    public:
        Coordinates(int, int);
        void setCoordinates(int, int);
};

For the setLoc method in the ball class, which parameters should is better? Would it be better to just setLoc by using (*ballCurrent).setCoordinates(int, int) OR by using (ballCurrent).setLoc((new Coordinates(int, int)))? Please go into detail the reason for each case if possible.

4

5 回答 5

3

更新指针的值还是将指针更改为指向其他东西更好?

这不是那种没有上下文就可以回答的问题。知道一个对象是不可变的通常很有用——只要你有一个指向那个对象的指针,这个对象就不会在你眼皮子底下改变。例如,如果一个函数或方法将一个指向不可变类型的指针作为参数,那么您就知道可以将对象传递给该函数,而不必担心该函数会更改该对象。

另一方面,可变对象也有自己的位置。一方面,您有时希望能够分几个步骤构建一个对象,而不是一次完成所有工作,并且您可能不希望在此过程中创建多个中间对象只是为了获得最终对象。

所以,这取决于上下文。我看到您提供了一个简单的示例,但我认为即使您的示例也不一定有正确的答案。这取决于对您来说什么是重要的,以及所讨论的对象将如何与系统的其他部分交互。我认为我倾向于使用可变对象,因为在游戏中可能需要多个对象了解球。如果移动球的唯一方法是创建一个新球并将其传递给所有其他关心它的对象,那么这很容易成为一个大问题。不过,坐标对象很容易是不可变的——任何需要知道球位置的人都应该向球询问它的位置。一旦他们得到它,他们可能会期望位置不会每隔几毫秒就改变一次。如果你不

于 2013-02-15T05:16:33.873 回答
1

如果可以的话,我可能会这样写:

class ball
{
    Coordinates coordinate_;     // better name than ballCurrent?
    public:
        explicit ball(int)       // add explicit to avoid implicit converting
        : coordinate_(0,0)       // initialize corrdinate_ properly
        {
        }
        ~ball();
        void setLoc(const Coordinates& co) // add const
        {
           coordinate_ = co;
        }

        void setLoc(int x, int y)
        {
           coordinate_.setCoordinates(x,y);
        }
};

无需担心动态内存问题,可以setLoc通过函数重载两种方式。没有野指针,不用担心。

于 2013-02-15T05:11:26.437 回答
1

如果您使用一个新对象,它将需要为自己分配内存,并且还需要对其进行初始化(构造函数/s 运行、分配属性等)。与仅更改您已经拥有的对象(以及您为此目的创建的对象)的值相比,这是很多开销。

此外,如果您创建一个新对象,则需要释放先前指针的内存,这又是开销……所以只需更改现有对象即可。

于 2013-02-15T05:13:16.170 回答
0

只需更改指向的对象的值。每次要更新值时都创建一个全新的对象是没有意义的。

如果 Coordinates 有一个 const x 和 y 值并且没有 setCoordinates 函数,您可能必须创建一个全新的对象而只是更改值的一种情况。但是,如果您需要经常更新坐标,那么这很可能是一个糟糕的设计决策。

也不是这个:

(*ballCurrent).setCoordinates(int, int);

你可以使用这个:

ballCurrent->setCoordinate(int, int);

它做同样的事情,但更容易编写,很多人会发现它更具可读性。

于 2013-02-15T05:13:52.923 回答
0

在 的情况下SetLoc(int,int),您正在创建构造函数之间ball和构造函数的Coordinates依赖关系Coordinates,更重要的是,它所代表的内容。如果构造函数签名发生更改,您必须将这些更改转移到ball::SetLoc. 这个参数在一般情况下是有效的,在这种情况下,您确实希望避免传递一组参数来初始化对象组件。

在这种特殊情况下,Coordinates体现了空间中的一个位置,并且可能应该附带一组方法来操纵它,以防止其实施细节渗透到程序的其余部分。如果您希望移动到 3D 坐标系,理想情况下,您只需要更改构造函数调用和类实现即可。因此,您确实希望将类外的必要更改减少到最低限度,这意味着要避免前面解释的问题。

您提出了两种不同的解决方案来设置ball对象的位置。在实践中会出现这些解决方案吗?在一个简单的程序中,球的位置是硬编码的,这是可能的,任何一种解决方案都可以工作。但在更复杂的软件中,球的位置可能最初由配置文件设置,并且在一些非平凡的计算之后完成任何后续的位置更新。(int, int)在这种情况下,将所有与坐标有关的逻辑都封装在类中,避免参数传递,更易于维护。

如果您担心内存分配开销(例如由函数返回的结果生成的临时内存),可以通过明智地使用常量、引用甚至指针来缓解它们,并定义合理的复制构造函数。

于 2013-02-15T05:22:27.167 回答