C++:是否绝对有必要手动分配内存
C++: Is it ever absolutely necessary to allocate memory manually?
我对C++编程的一些更高级的方面相对较新,我很难理解是否真的有必要在C++中分配内存(无论是通过malloc,new等(。例如,在 C 中,我知道您需要分配内存才能拥有动态大小的数组或其他任务。C++,在我看来并非如此,你可以使用 std::vector、std::string 或其他已经通过设计动态调整大小的内置方法。我也明白访问分配的内存比堆栈慢。
因此,鉴于此,是否有时间必须C++分配内存,如果是这样,其中一个时间的示例是什么?当然,这不包括您的C++代码必须与 C 程序交互的时间。让我们假设程序纯粹是用C++编写的。
编辑:为了减轻混乱,我知道向量和其他结构正在分配自己的内存,但这是幕后发生的事情,不需要程序员使用new,malloc等,它会自动清理。所以我真正想知道的是,是否有必要在 C++
堆栈的大小有限,有些东西无法可靠地放入其中。动态分配的内存还具有动态特性,有时您不确定数组中需要多少个对象或元素,直到程序执行的某个时刻。
看看这个问题,它在描述每个可能的用例方面做得很好:
当您希望比上述更灵活时,堆分配(动态分配的内存(非常有用。通常,调用函数来响应事件(用户单击"创建框"按钮(。正确的响应可能需要分配一个新对象(一个新的 Box 对象(,该对象应该在函数退出后很长时间内仍然存在,因此它不能在堆栈上。但是你不知道在程序开始时你想要多少个盒子,所以它不可能是静态的。
反映您的编辑:事实上,它并不是真正需要的,或者更确切地说,它通常被抽象出来,就像vector
和string
一样。您有各种容器,例如vector
可以为您处理这些容器。当您设计自己的类时,我们鼓励您使用资源分配即初始化 (RAII( 技术,该技术抽象出典型的手动内存管理。事实上,在某些情况下,尤其是在处理 C 代码时,我们鼓励您在使用 RAII 的 C++ 类包装器中或使用C++智能指针(如 C++11:shared_ptr
和 unique_ptr
(它们本身使用 RAII(中引入的那些(来管理该内存。
例如,在 C 中,我知道您需要分配内存才能拥有动态大小的数组或其他任务。在C++中,在我看来并非如此,您可以使用 std::vector 或其他已经通过设计动态调整大小的内置方法。
不过,std::vector
并不是建立在魔法和仙尘之上的:它在内部分配记忆。
您是对的,C++您很少需要手动分配内存。在某些情况下,这是最简单的方法,尽管1.关键是C++使得手动释放完全没有必要,因为析构函数会处理这个问题。
1 非常非常罕见。 大多数写得很好的代码根本不需要这个。在处理较低级别的详细信息时(例如,在实现容器时(,它偶尔很有用。
如果你的问题是,">动态分配的内存在C++中是不必要的吗?答案是,这是非常必要的,而且非常重要。
如果您的问题是,">使用现代 C++11 类和功能,我的代码多久需要我手动使用'new'和'delete'">?
答案是"很少"。大多数新建和删除调用将隐藏在容器(std::vector,std::map等(和智能指针(std::shared_ptr和std::unique_ptr(中,并通过对std::make_shared((等函数的调用。
在极少数情况下,您是否需要手动调用"新建"和"删除"?这取决于您正在制作的程序类型,但如果它们是视频游戏,我会说是的,可能是 1% 的时间(我的经验,但 YMMV(,您需要使用手动 new 并通过 std::make_shared(( 和 std::shared_ptr 删除 - 尽管同样,这取决于项目。
一般来说,首选在堆栈上分配的局部变量和成员变量(忽略它们是否在内部分配动态内存(,接下来更喜欢 C++11 托管动态内存(智能指针(,最后诉诸 new 和删除作为最后的手段,如果性能需要它(但不要预先优化 - 分析并找到真正的瓶颈(。
请注意,仅仅因为您使用智能指针管理内存,并不意味着您应该禁止代码中的所有原始指针 - 即使您的所有内存都在管理中,与内存生命周期管理无关的原始指针仍然非常实际。
正如你所观察到的,永远没有必要将new
与标准容器一起使用(vector
、map
等(。
使用智能指针时,使用make_shared
总是比new
shared_ptr
更好;因为unique_ptr
缺少make_unique
是一个缺陷(make_unique和完美的转发(,应该尽快解决;复制粘贴和使用make_unique
比自己new
unique_ptr
更好, 出于清晰和异常安全的原因。
如果您正在编写自己的容器,请在可能的情况下尝试编写标准库工具(现有容器和智能指针(,这样您就不必担心生存期管理。
有一个标准工具需要使用new
;默认情况下,采用Facet *
的std::locale
的模板化构造函数期望由new
分配Facet *
,因为一旦它不再被std::locale
实例使用,它就会被delete static_cast<locale::facet*>(f)
处置。 (请注意,std::locale::facet
有一个虚拟析构函数。 如果这让您感到不舒服,您可以通过在构造分面时将1
作为refs
参数传递来安排自己管理分面的生命周期:在区域设置(std::locale(中拥有/删除分面。
你不需要自己。我一直在做下面这样的事情
void foo(MyStruct&v) { v.bar=1234 }
vector<MyStruct> v;
v.push_back(...);
本质上,单个值在堆栈上,而集合在堆栈上,但将所有内容放在一个堆中。我从不在大多数应用程序中使用新的关键字或指针。
- 在c++中为我自己的基于指针的数组分配内存的正确方法
- 给定一个指向堆分配内存的指针,智能指针实现如何为其找到合适的释放函数?
- 如果 const 不分配内存,为什么我可以获取 const 的地址?
- 在函数中分配内存时出现问题
- 如何为 std::vector 分配内存,然后稍后为某些元素调用构造函数?
- constexpr new 如何分配内存?
- 在构造函数中分配内存失败是如何冒泡的
- LLVM 传递以在特定地址分配内存
- CudaMalloc 在分配内存时失败
- 为什么它在不分配内存的情况下工作正常
- 为什么在正确解除分配内存时出现内存泄漏?
- 如何通过 malloc 为队列数组分配内存?
- vector是否为std::移动的对象连续分配内存
- 删除类成员的动态分配内存的最佳方法是什么
- 唯一指针是否在堆或堆栈上分配内存?
- 如果不分配内存,我如何能够为变量创建和分配值?
- std::initializer_list 堆是否分配内存?
- 如何按顺序或在指定的地址分配内存?
- 是否可以使用 malloc 为类对象分配内存?
- 迭代器是否分配内存(如指针)?