c对象实例化
我是想理解c的c程序员。 在许多教程中,您将使用以下代码段来实例化对象:
Dog* sparky=new Dog (;
这暗示着你接下来会这么做:
删除火花;
这是有道理的。 其中,如果不需要动态内存分配,有理由使用上述替代吗
杜斯帕利;
sparky超出范围时是否要调用析构函数?
谢谢你!
El _ champoasked 2019-07-11t 04336020336045 z
9个解决方案
160伏特
相反,您应该始终喜欢堆栈分配。 用户代码在某种程度上不应该有新的/删除。
正如您所言,当变量在堆栈上声明时,它将在超出范围时自动调用。 这是跟踪资源生命周期和避免泄漏的主要工具。
因此,通常每次需要分配资源时,构造函数都会包装在获取资源的类中,而不管内存、文件句柄、套接字或其他什么,从而释放析构函数。 然后,可以在堆栈中创建该类型的对象,并在资源超出范围时释放资源。 这消除了在任何地方跟踪新的/删除对以确保避免内存泄漏的需要。
这个成语最常见的名字是RAII
另外,如果需要将新内容分配到专用RAII对象外部,还将考虑用于包装结果指针的智能指针类。 将指针传递给智能指针,智能指针跟踪其生命周期。 例如,通过引用计数,在最后一个引用超出范围时调用析构函数。 标准库使用std:unique_ptr进行简单的基于范围的管理,使用std:shared_ptr引用计数以实现共享所有权。
在许多教程中,您将看到对象是使用片段(如.实例化的
所以你发现的大部分教程都很糟糕。 )大多数教程都教坏c的实践,如调用new/delete在不需要时创建变量和跟踪分配生命周期的困难。
jalf answered 2019-07-11t 04:21336049 z
21电压
堆栈上的东西在分配和自动释放方面可能是优点,但也有一些缺点。
您可能不想为堆栈分配大对象。
动态调度! 考虑以下代码:
#包含
类a {
公共:
虚拟语音f (;
虚拟到a (}
(;
class b :公共a {
公共:
虚拟语音f (;
(;
void A:f () {cout 'A ); }
void B:f () {cout 'B '; }
输入主(语音) {
A *a=new B (;
a-f (;
电传a;
返回0;
}
这将打印“b”。 让我们看看使用堆栈会怎么样。
输入主(语音) {
a=b (;
a.f (;
返回0;
}
这印成“a”,对于熟悉Java和其他面向对象语言的人来说可能不太直观。 原因是没有指向a实例的指针。 而是创建a的实例并将其复制到A*类型的变量a中。
有时不会凭直觉发生。 特别是在mmdll不熟悉c的情况下。 在c你有你的指南是这样的。 你知道它们的使用方法,它们总是一样的。 在c,情况并非如此。 想象一下,如果mmdll在本例中使用a作为方法的参数,会发生什么。 如果a类型为a或A*或甚至a,则通过引用调用。 可以有很多组合,行动不同。
通用安全2019-07-11t 0433602:00 z
13电压
那么,使用指针的理由与在malloc中分配的c中使用指针的理由完全相同。 如果你希望对象比变量长寿
如果可以避免使用新操作员,强烈建议不要使用它。 特别是如果使用例外的话。 通常,让编译器释放对象比较安全。
pierrebdranswered 2019-07-11t 0433602:34 z
13电压
我没有完全得到这个反模式&; amp; 职业地址。 如果需要使用指针调用函数,它将始终分配给堆以检索指针。
voidfeedthedog(dog*Hungrydog;
Dog* badDog=new Dog;
feedthedog(baddog );
删除baddog;
狗粮;
FeedTheD
og(&goodDog);Mark Ransom answered 2019-07-11T04:24:02Z
7 votes
将堆视为一个非常重要的房地产,并非常明智地使用它。 基本的拇指规则是尽可能使用堆栈,并在没有其他方法时使用堆。 通过在堆栈上分配对象,您可以获得许多好处,例如:
(1)。 如果出现异常,您无需担心堆栈展开
(2)。 您不必担心由堆管理器分配的空间超出所需的内存碎片。
Naveen answered 2019-07-11T04:24:44Z
5 votes
我担心的唯一原因是Dog现在被分配在堆栈上,而不是堆。 因此,如果Dog的大小为兆字节,则可能会出现问题,
如果确实需要使用新的/删除路由,请注意例外情况。 因此,您应该使用auto_ptr或其中一种boost智能指针类型来管理对象的生命周期。
Roddy answered 2019-07-11T04:25:18Z
1 votes
mmdll可以在堆栈上分配时,没有理由新(在堆上)(除非由于某种原因你有一个小堆栈并想要使用堆。
如果您想在堆上分配,可能需要考虑使用标准库中的shared_ptr(或其变体之一)。 一旦对shared_ptr的所有引用都已经存在,那将为您执行删除操作。
Scott Langham answered 2019-07-11T04:26:00Z
0 votes
还有一个原因,没有其他人提到过,为什么你可以选择动态创建对象。 动态的,基于堆的对象允许您使用多态。
dangerousdave answered 2019-07-11T04:26:29Z
-4 votes
我在Visual Studio中遇到了同样的问题。 你必须使用:
yourClass->类方法();
而不是:
yourClass.classMethod();
Hamed answered 2019-07-11T04:27:10Z