所以,我要说我有一个班级MyClass
。现在我想使用另一个名为Animals
的类,我可能会执行以下操作。
class MyClass
{
public:
MyClass();
private:
Animals animals;
};
但我也可以这样做:
class MyClass
{
public:
MyClass();
private:
Animals* animals;
};
然后使用:
在构造函数中初始化类animals = new Animals();
两种不同的方法有什么区别,哪种更好,为什么?在我的使用中Animals
应仅在MyClass
内使用。我的问题主要是关于性能和内存,我的意思是指针初始化需要更多资源吗?
答案 0 :(得分:5)
如果你考虑如何在一个类中管理内存,它应该变得清晰。当您在班级中声明Animals animal
时,会在班级的内存空间中为animal
保留空格。但是当你声明Animals* animal
时,只有一个指向Animal
的指针被保留在你班级的内存空间中。
两者都不好,因为这取决于你的情况。如果你总是要创建一个动物并且MyClass
拥有它,那么使用第一种方法,因为它只需要一次内存分配。如果animals
通常是空的并且内存是一个问题,那么您可能想要使用第二种方法。
顺便提一下,如果您使用的是C ++ 11或更高版本,则可能需要考虑第二种情况std::unique_ptr<Animal>
。
答案 1 :(得分:1)
如果animals
对象的唯一存在取决于MyClass
对象,则使用包含:
class MyClass
{
public:
MyClass();
private:
Animals animals;
};
如果animals
的存在是独立的,但MyClass
想要与之保持关联,则使用指针:
class MyClass
{
public:
MyClass();
private:
Animals * animals;
};
选择取决于对象所有权模型。
涉及许多考虑因素。
在包含方法中,animals
的内存与MyClass
对象一起分配。他们总是在一起MyClass
完全拥有 animals
。
在指针方法中,它们是两个独立的内存块,需要单独分配。这是一个没有任何所有权的协会。在MyClass
的整个生命周期中,可能会发生多种事情:
myclass
不与任何Animals
相关联,即animals = nullptr
myclass
可能会在不同时间与不同的Animals
相关联,即animals = a1; /* ... */; animals = a2;
此外还有多个对象,MyClass
个对象或其他类型的对象, may hold the same
动物`指针。
如果animals
对象被销毁,那么这些对象就有使用陈旧指针的风险,因此需要一些机制来避免这种情况。
使用指针方法,可以使用运行时多态,这在包含方法中是不可能的。例如
void MyClass::setAnimal(Animal * a) {
animal = a;
}
Animal * a1 = new Lion;
Animal * a2 = new Tiger;
MyClass x1;
x1.setAnimal(a1);
MyClass x2;
x2.setAnimal(a2);
答案 2 :(得分:0)
从设计的角度来看,MyClass
是一个Animal
的容器。在第一个示例中,您始终拥有Animal
。在第二个示例中,您可能拥有Animal
,也可能没有Cardinality
。
例如,如果你有一只带鸟的笼子,你的第一个笼子总是有一只鸟,它不能没有鸟,但第二个例子你可能有也可能没有鸟。
这在数据库中称为Animals
(0,1)。你可以把它想象成一个Animal
的集合,有一个或零个元素(甚至很难你没有数组)。
第二个方面是,在第一个示例中,您始终拥有相同的Animal
,并且您无法自由传递它,Animal
的生命周期完全取决于容器。第二个示例允许将Animal
移动到新容器或在两个不同的容器中使用相同的Animal
,并将{{1}}的生命与容器分离。
然后,使用C ++,您必须考虑内存分配和所有权,我们通常使用智能指针来释放动物。