我正在开发一个项目,其中我使用了很多课程。 为了创建类,我使用了new运算符...例如,在banana类中,我有一个类apple的实例变量......
这是我想要说的一个缩小的代表性&没有代表这个代码的字样......所以请不要指出语法错误......但是要理解方法论
在头文件(banana.h)中:
static int counter = 0;
class banana
{
public:
apples *ap_obj;//(apple is a class defined another file apples.cpp)
int *index;
}
在banana.cpp中:
class banana
{
banana::banana(void)
{
ap_obj = new apples;
index = new int;
*index = ++counter;
}
};
我的第一个问题是,我的方法在内存效率方面是否正确? (我知道我确实没有任何运行时错误)
我的第二个问题是,我想通过使用索引(plz注意每个香蕉对象具有唯一索引)变量来访问任何类的一个方法中的香蕉对象。 为此,我正在考虑使用另一个类注册表(因为我想存储许多类的对象的索引)。 我正在考虑将任何类的第一个对象的指针存储在我的注册表类中。 &安培;为了访问类的任何第n个对象的指针,我计划使用索引变量在第一个对象上使用指针算术...示例
class registry
{
banana *base_obj;//this value will be initialised when i create the 1st object of banana class
banana *registry::get_nth_object(int shift);
{
return *(base_obj + shift);//shift is the index variable of banana class
}
};
在任何其他课程中我都可以致电 get_nth_object &传递指针我想要的对象的索引号&我会明白这一点。
我的代码有什么问题吗? 或者如果有任何改进可以帮助我。
参考我使用http://www.cplusplus.com。 我是一名机械工学生,所以请原谅我,如果我犯了任何愚蠢的错误
答案 0 :(得分:3)
直接嵌入更节省内存(它可以节省指针和堆分配的开销,并提高引用的局部性):
class banana
{
private:
apples ap_obj;
int index;
}
请注意,您忘记了原始代码中的new
索引。我甚至不确定我是否理解它的必要性。仅使用 来查找特定的banana
吗?如果是这样,它根本不应该是banana
的成员。为什么还要存储索引呢?引用特定实例的常用方法是使用banana*
。
答案 1 :(得分:1)
首先,香蕉构造函数本身的语法不正确。它不应该被文本类banana {};
包围其次,使用new在堆上分配内存将足够快,以满足您的需要。你不应该以任何其他方式这样做(即不要使用malloc)。所以你在这一点上很好。
至于你的注册表示例,get_nth_object只有在你的所有香蕉实例都分配到连续的内存区域时才会起作用....你在使用new分配内存时无法控制。如果你使用新的香蕉[size]为你的香蕉指针分配内存会更好,并且内存将是连续的。
即使你确实在内存中定期间隔它们,如果你需要删除香蕉怎么办?还是两三个?还是打了半打?很快你就会做一些真正强烈的记录保持工作。
我自己更喜欢在创建时为其构造函数中的每个香蕉分配一个唯一的ID,并在banana的构造函数中将自身插入到关联容器中,如地图(即std :: map)(在代码中使用#include) 。我将使用唯一ID作为键,然后您可以使用指向香蕉的指针作为值。在香蕉的析构函数中,我会将香蕉从注册表中删除。
您的注册表将负责拥有关联容器(即地图)。
答案 2 :(得分:0)
我知道我确实没有任何运行时错误
好吧,似乎你有运行时错误(或更多)。声明
int *index;
将index
作为未初始化的指针,然后
*index = ++counter;
将counter
的内容放到index
指向的位置(这可能是完全未定义的位置)。当然这会导致奇怪的错误。
也许你想申报
int index;
和
index = ++counter;
我假设?
答案 3 :(得分:0)
要存储标量数据,您不需要使用指针。这就是int index
的原因。分配一些“不可能”的值来知道索引是非法的。
您的方法get_nth_object
错误。您无法确定是否在一致的内存块中分配了所有banana's
。因此,您不能使用这种线性地址算法来获取对象。查找有关使用动态数组或列表的信息。如果是数组,您可能需要检查有关重载订阅运算符的信息
答案 4 :(得分:0)
首先,你应该找出你的香蕉与苹果关系是什么类型的关系。如果它是一种成分(香蕉由其苹果和......组成),最简单的想法是将苹果实例存放在香蕉中。
class banana
{
apple apple_; // a banana HAS A apple
};
如果这是真的,但你有无数的香蕉,并且有许多苹果等于你可以实现Flyweight Pattern安全内存使用。但是你不应该这样做,因为你认为你有记忆问题,但是因为你因为苹果而导致记忆问题。
如果您的关系更多是共享所有权,则应该在apple中存储指向apple实例的指针,并考虑存储苹果对象的位置。最简单的方法是存储std::shared_ptr<apple>
并让参考计数器控制苹果的生命周期。
您的第二个问题是如何存储和访问香蕉对象。我会介绍一个负责存储和检索香蕉的BananaRepository
。
class BananaRepository
{
typedef XYZType BananaID;
Banana& GetByID(BananaID id);
BananaID Add(Banana& b);
};
您应该抽象使用的ID和存储的类型,因此客户端代码不依赖于该细节。每个香蕉都有一个ID,我可以使用此ID从存储库中获取香蕉。最简单的实现是使用banana :: ID = vector :: size_type和BananaRepository中的向量。
class BananaRepository
{
public:
typedef std::vector<Banana>::size_type BananaID;
Banana& GetByID(BananaID id)
{
return bananas_.at(id);
}
BananaID Add(Banana& b)
{
bananas_.push_back(b);
return bananas_.size() - 1;
}
private:
std::vector<Banana> bananas_;
};