减少内存使用
reducing memory usage
我正在开发一个项目,我在其中使用了许多类。对于创建类,我使用了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;
}
in banana.cpp:
class banana
{
banana::banana(void)
{
ap_obj = new apples;
index = new int;
*index = ++counter;
}
};
我的第一个问题是,我的方法在内存效率方面是否正确?(我知道我肯定没有任何运行时错误)
我的第二个问题是,我想通过使用索引(请注意,每个香蕉对象都有一个唯一的索引)变量来访问任何类的一个方法中的香蕉对象。为此,我正在考虑使用另一个类注册表(因为我想存储许多类对象的索引)。我正在考虑将任何类的第一个对象的指针存储在我的注册表类中。,为了访问类的任何第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。我是一名机械工程专业的学生,所以请原谅我,如果我犯了任何愚蠢的错误
直接嵌入是更节省内存的(它节省了指针的开销和堆分配的开销,并提高了引用的局部性):
class banana
{
private:
apples ap_obj;
int index;
}
注意,您在原始代码中忘记了new
索引。我甚至不确定我是否理解它的必要性。仅用于查找特定的banana
吗?如果是这样,它就不应该是banana
的成员。为什么要存储索引呢?引用特定实例的通常方法是使用banana*
。
首先,banana构造函数本身的语法是不正确的。它不应该被文本类banana {};
包围其次,使用new在堆上分配内存对于您需要做的事情来说足够快。你不应该以任何其他方式(即不要使用malloc)。所以你在这一点上很好。
对于您的注册表示例,get_nth_object仅在所有banana实例都分配在连续的内存区域....中才能工作当您使用new分配内存时,您无法控制。如果你为你的香蕉指针分配内存使用新的香蕉[size]会更好,内存将是连续的。
即使你让它们在内存中有规律地间隔,如果你需要删除一个香蕉怎么办?还是两三个?还是半打?很快,你将不得不做一些真正紧张的记录来保持工作。
我自己更喜欢在创建香蕉的构造函数中为每个香蕉分配一个唯一的ID,并在香蕉的构造函数中将自己插入到一个关联容器中,如map(即std::map)(在代码中使用#include)。我将使用唯一ID作为键,然后你可以使用指向香蕉的指针作为值。在banana的析构函数中,我会让banana从注册表中删除自己。
您的注册中心将负责拥有关联容器(即映射)。
首先你应该找出你的香蕉->苹果是哪种关系。如果它是一个组合(香蕉是由它的苹果和…组成的),最简单的想法是在香蕉中存储一个苹果实例。
class banana
{
apple apple_; // a banana HAS A apple
};
如果这是真的,但是你有无数的香蕉和数量相等的苹果,你可以实现Flyweight模式来安全使用内存。但是你不应该因为你认为你有记忆问题而这样做,而是因为你测量到你因为苹果而有记忆问题。
如果你们的关系更像是一个共享的所有权,你应该在banana中存储一个指向apple实例的指针,并考虑在哪里存储apple对象。最简单的方法是存储std::shared_ptr<apple>
,并让引用计数器控制apple的生命周期。
你的第二个问题是如何存储和访问香蕉对象。我将介绍一个BananaRepository
,它负责储存和提取香蕉。
class BananaRepository
{
typedef XYZType BananaID;
Banana& GetByID(BananaID id);
BananaID Add(Banana& b);
};
您应该抽象所使用的ID和存储的类型,这样客户端代码就不依赖于这些细节。每个香蕉都有一个ID,我可以使用这个ID从存储库中获取香蕉。最简单的实现是在bananarerepository中使用banana::ID = vector::size_type和一个vector。
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_;
};
我知道我没有任何运行时错误
嗯,似乎你有运行时错误(或更多)。声明
int *index;
使index
成为未初始化的指针,
*index = ++counter;
将counter
的内容放在index
指向的位置(这可能是完全未定义的)。这肯定会导致奇怪的错误。
也许你想声明
int index;
和
index = ++counter;
我想吗?
-
对于存储标量数据,您不需要使用指针。这就是为什么
int index
。 指定一些"不可能"的值来知道索引是非法的。 你的方法
get_nth_object
是错误的。您不能确保所有banana's
都分配在一致的内存块中。因此,您不能使用这种线性地址算法来获取对象。查找有关使用动态数组或列表的信息。对于数组,您可能希望检查有关重载订阅操作符 的信息。
- 将字符串存储在c++中的稳定内存中
- C++ 指针的内存地址和指向数组的内存地址如何相同?
- Win32编译器选项和内存分配
- 当vector是tje全局变量时,c++中vector的内存管理
- 带内存和隔离功能的SQLite
- 是否可以通过C++扩展强制多个python进程共享同一内存
- 迭代时从向量和内存中删除对象
- 在C++中打印指向不同基元数据类型的指针的内存地址
- 这个指针和内存代码打印是什么?我不知道是打印垃圾还是如何打印我需要的值
- 多个文件的内存分配错误"在抛出 'std :: bad_alloc' what (): std :: bad_alloc 的实例后终止调用" [C++]
- 为什么示例代码访问IUnknown中已删除的内存
- 如何在C++类内存结构中创建"spacer"?
- 从构造函数抛出异常时如何克服内存泄漏
- malloc() 可能出现内存泄漏
- 如何理解将半精度指针转换为无符号长指针和相关的内存对齐
- 在调用FreeLibrary后,释放动态链接到具有相同版本的CRT堆的DLL的内存
- 如何针对特定情况调试和修复此双自由内存损坏问题
- 类型总是使用其大小存储在内存中吗
- 有没有一种方法可以测量c++程序的运行时内存使用情况
- 有没有一种方法可以使用placement new将堆叠对象分配给分配的内存