动态分配的用法

时间:2013-08-08 17:33:39

标签: c++ dynamic-memory-allocation

来自Java和C#,我习惯于做以下事情:

byte[] myArray = new byte[10];

并不关心必须清理它。但是,现在我正在使用C ++,你显然必须小心分配和内存泄漏。

我听说有些人说你应该不惜一切代价避免动态分配,但我也看到有些人使用new运算符“自由地”使用它当本地堆栈变量足够时实例化类:

DatabaseConnection conn = new DatabaseConnection("127.0.0.1");
// or
DatabaseConnection conn("127.0.0.1");

我知道在堆上分配的数组要慢得多,但我希望通过使用动态内存可能导致的小的性能损失来获得更具可读性和可扩展性的代码。

所以,我的问题是:你是否应该不惜一切代价避免堆分配?

5 个答案:

答案 0 :(得分:5)

我建议在这种情况下,使用它很好:

byte myArray[10]; 

如果您需要一个阵列,您可以复制(例如从函数返回),然后使用vector<byte>是正确的解决方案。

最后的手段应该是使用new,并且如果数据需要在函数外部预先分配,则仅分配小区域。

不幸的是,书籍并不总是告诉你好的做法,或者显示你应该和不应该使用的好例子,例如new - 相反,他们会显示int *arr = new int[5];之类的内容 - 可能占用的开销空间比实际数据多。

当然,所有new必须为deleted。使用智能指针(shared_ptrunique_ptr)可以通过自动清理帮助很多。

答案 1 :(得分:4)

什么时候可能?是。不惜一切成本?不会。动态分配通常是解决问题的最简单方法。

但是, 几乎不惜一切代价使用new。依靠make_sharedmake_unique生成单个对象,以及std::vector之类的容器可以生成多个对象。你没有理由使用delete

答案 2 :(得分:1)

是的,你应该尽可能避免堆分配。在您提到的情况下,您应该使用标准库提供的容器,如std::vector<byte>,如评论中所建议的那样。

如果绝对必须在堆上存储内容,请使用RAII(资源获取是初始化),这意味着在构造时执行获取的对象(在堆栈上),并在销毁时释放资源。从C ++ 11开始,std::unique_ptr就是std::shared_ptr,或者更复杂的std::weak_ptr(连同std::unique_ptr<int> unique(new int(42)); auto sp = std::make_shared<int>(42); ),如果您需要资源的多个所有者:

scoped_ptr

如果你还不能使用C ++ 11,几乎每个库都会为你提供某种smartpointer - boost会给你scoped_array / shared_ptrshared_array / {{1} },weak_ptrintrusive_ptr; Poco给你AutoPtr等等。在C ++ 03中甚至有一个smartpointer,auto_ptr,但我强烈反对使用那个;它的使用现已弃用,并且它具有非常奇怪的复制行为,因为C ++ 03不支持rvalue引用/移动语义。

答案 3 :(得分:1)

你总是可以从两个向量中处理这些问题;可维护性/可读性和性能。有时第二个是重要的,有时不是。有时你不关心第一个。但是,在这种情况下,我会说尽可能在自动内存(“堆栈”)和动态内存(“堆”)上放置内容在两个点上都会获胜(大部分时间)。

与更改堆栈指针相比,分配动态内存非常慢,几乎没有关于性能的论据。但是如果你分配的东西不会将其范围留在动态内存中,你必须注意在范围之后释放内存,如果你忘了,你不仅仅是泄漏内存,你可能会破坏正确性,因为析构函数不称为。在这方面它的可维护性较差。

对每一个new持怀疑态度,并认为它有点臭。它可以防止你不必要地过度使用它。

答案 4 :(得分:0)

动态分配的一些问题:

  1. 内存泄漏(如果您忘记删除对象)
  2. 大量的alloc / free请求 - 另一方面,堆栈分配只是在调用函数时移动堆栈指针一次。有些自动变量甚至可能驻留在寄存器中而不会占用内存。
  3. 堆碎片。
  4. 基本上,只有在你用完所有其他选项时才使用堆。