我应该将所有对new / delete的调用集中到一个类吗?

时间:2011-09-18 00:16:07

标签: c++ memory-management stl

目前,我的所有对象都在管理自己的内存,通常在其构造函数中使用new进行分配,并在析构函数中使用delete。这适用于现在,但我使用任意数量的内存的类的数量正在增长。 new本质上是一个“请求”的事实也困扰我,因为这些对象中没有代码来处理被告知“不”,如果我不需要,我不想依赖异常处理至。

  • 在性能方面完全有益 将所有分配内存的调用屏蔽到一个处理的类 堆上的每个内存分配,可能分配大块 一次并使用placement new来处理引用?

  • 在较小的类中使用内存分配是否足以引起人们的关注呢?

  • 我仍然可以使用STL容器并强制它们使用堆I 提供

提前谢谢!

5 个答案:

答案 0 :(得分:4)

  

我仍然可以使用STL容器并强制它们使用我提供的堆吗?

STL容器接受自定义分配器:

http://en.wikipedia.org/wiki/Allocator_(C%2B%2B)#Custom_allocators

这是一个包含样本链接的主题:

Compelling examples of custom C++ allocators?

  

在性能方面是否有益......?

您只能通过编写应用程序,提出一组可重现的测试方案,并在分析器中运行代码来查找。如果您发现内存分配是运行时间的重要部分,那么您可能会从更好的分配策略中受益。

如果您可以将程序分解为功能级别,并且可以针对每种情况提出实际场景,则无需让整个程序执行此操作。但请记住,花在优化上的时间是花在测试或编写新功能上的时间:)做必要而且不再需要......

  

在较小的类中使用内存分配是否足以让人费心呢?

根据您的程序,您对大分配故障的敏感程度,您在循环中分配的频率等等,这是可能的。简介:)

在开发应用程序时,您仍然可以对分配敏感 - 尽可能创建自动存储(堆栈本地)变量,并且只在必要时动态分配。

答案 1 :(得分:3)

我不确定我在这里理解你的问题。也就是说,将C ++ 03中的STL容器与自定义堆一起使用将具有挑战性,因为分配器被认为是无状态的。另外,为什么你不想依赖异常处理?你知道有新的no_throw版本吗?

编辑:像这样调用new的无抛出版本:new (std::nothrow) Type[size];。如果分配失败,它将返回空指针(0),而不是抛出std::bad_alloc

答案 2 :(得分:3)

  

我仍然可以使用STL容器并强制它们使用我提供的堆吗?

是的,查找STL allocators

  

在性能方面完全屏蔽所有分配内存的调用,处理堆上每个内存分配的单个类,可能一次分配大块并使用placement new来处理引用是否有益?

这基本上是mallocnew的良好实施。我不推荐自己做,除非情况非常性能至关重要,其他一切都已经过优化。为什么?因为内存管理的良好和深思熟虑甚至很难实现无错误,更不用说优化工作了。

  

在较小的类中使用内存分配是否足以让人费心呢?

这取决于,如果您正在使用16k内存编程咖啡机或游戏设备,但是在普通台式计算机或笔记本电脑上可能没有。还记得堆栈非常快(分配和访问),而堆在分配上要差很多,并且在使用时略微(不太确定TBH),所以在日常情况下你想要更喜欢堆栈。

答案 3 :(得分:2)

我以前做过这个,这是我的经历:

  1. 它很快就会变得非常混乱。特别是因为你现在把内存分配到你的手中,你必须处理像碎片和重新入侵这样的东西。
  2. 但是,由于能够绕过操作系统开销,我看到性能提升高达20%
  3. 对于你的上一个问题,我认为有一种方法可以让他们使用自定义分配器,但我以前从未这样做过。我在C中完成了大部分编码。

    编辑:

    根据您的评论,这是一个更新。你真的不必处理构建分配器。只需将所有内存分配指向您的自定义类,您就可以逃脱。然后,您的自定义类将调用malloc()new并捕获返回的任何NULL或异常。

    (虽然用自己的new替换每一个malloc()需要一些工作。)

答案 4 :(得分:2)

你说你在你的构造函数中调用new ......这真的有必要吗?我的意思是,而不是......

class A{
    std::vector<int>* v;
    A( int vectorSize ){
       v = new std::vector<int>( vectorSize, 0 );
    }
    ~A(){
       delete v;
    }
};

......总是喜欢这样做:

class A{
    std::vector<int> v;
    A( int vectorSize ):
       v( vectorSize, 0 ){
    }
};

这样可以避免使用堆。只有在没有其他选择时才应该使用堆。

除此之外,与其他人一样,编写自定义分配器是一项非常复杂的任务,只能在性能关键的情况下完成