我需要销毁 new class 的每个实例吗?
Do I need to destroy each instance of new class?
本质上,如果我创建一个新的 class 的多个实例,我是否需要为每个实例调用析构函数,或者在每个实例销毁后调用它(如果我使用 [=,我深表歉意) 21=] 个术语,constructors/destructors 是我还没有完全掌握的概念)。
更具体地说,这是我正在使用的一些代码(如果风格不好,我将不得不再次道歉,我有一个学校问题的想法,想尽快把代码写下来) .
while(read >> f >> l >> t >> s >> sta >> acct >> bal)
{
cout << "test" << endl;
ptr[i] = new account(f,l,t,s,sta,acct,bal);
ptr[i]->printcontents();
cout << "test" << endl;
i++;
cout << i << endl;
}
所以为了这个问题,假设这将循环三次。我是否只需要调用一次 "account" 的析构函数来销毁新帐户的所有三个实例,或者一个调用会离开另外两个?这甚至是一个好习惯吗?
编辑:我注意到我的一些 post 被截断了,所以我添加了最后几行,但人们已经解决了这个问题。我是用户指针的原因纯粹是因为作业要求我这样做;坦率地说,我现在看不到使用它们的意义,但我认为它们会在某个地方变得有用。我还应该补充一点,动态内存分配也应该用于分配。
每个 new
应该用 delete
来平衡
如果您有一个指针数组,并且每个指针 new
,则每个实例需要 delete
。
另一方面,如果您 new
对象数组,则可以 delete []
整个数组。
附带一点,对于您的代码,而不是使用 ptr
(您没有告诉我们详细信息,请考虑仅使用 std::vector<account>
并使用 push_back
然后它将根据需要自动调整大小,而不是 ptr[i] = new...
.
析构函数会自动调用,您通常不必担心 除非您使用 new
.
动态分配内存
在这种情况下,一旦您不再需要分配的每个内存,就必须调用 delete
。
请注意,如果您使用 new []
分配数组,则必须使用 delete[]
进行取消分配:
int *a = new int[10]; // allocating an array of 10 integers
//...
delete[] a; // release memory
在现代 C++ 中,您应该考虑托管指针来完成这项工作。类似于:
while(read >> f >> l >> t >> s >> sta >> acct >> bal)
{
cout << "test" << endl;
ptr[i] = std::make_unique<account>(f,l,t,s,sta,acct,bal);
ptr[i]->printcontents();
cout << "test" << endl;
i++;
cout << i << endl;
}
在这里,std::make_unique
将 return 一个 std::unique_ptr
将在销毁时调用关联内存上的 delete。
最后一点:你确定你真的需要指点吗?从你的例子很难说,但根据你的使用情况,你也可以创建静态分配的对象:
while(read >> f >> l >> t >> s >> sta >> acct >> bal)
{
cout << "test" << endl;
ptr[i] = account(f,l,t,s,sta,acct,bal);
ptr[i].printcontents();
cout << "test" << endl;
i++;
cout << i << endl;
}
通常您必须删除您创建的每个实例。具体怎么做取决于一点……但简单的经验法则:
每次使用 new
都必须使用 delete
。
每次使用 new[]
都必须使用 delete[]
。
如果您从自动声明中获取实例,则无需执行任何操作,因为它将连同其堆栈框架一起销毁;但如果你创造了它,你就摧毁了它。
正如其他人所指出的,如果你使用new
,那么你将需要delete
。但是,您真正的麻烦是概念上的。你问了一个很好的问题 new
和 delete
是外围的。
99.5% 以上的正常使用析构函数是为了让编译器自动调用它们。 (0.5% 的例外是深奥的。我们现在不需要担心这个。)
考虑这个代码片段:
int n = 5;
{
int m = 2;
++m;
n *= m;
// The variable m is automatically destructed here.
}
// Here, n == 15.
看看效果如何? m
的析构函数在 m
到达其生命周期结束时自动调用,这(因为 m
不是用 new
创建的)发生在块的末尾m
被实例化。
当然,m
是一个 int
,因此它的析构函数不执行任何操作(或者,如果您愿意,m
没有析构函数)。您自己定义的其他类型,例如您的类型 account
,可以有析构函数。当单个对象(account
的一个实例)到达其生命周期的尽头时,针对单个对象自动 调用析构函数。
新建和删除
那么,这与new
和delete
有什么关系呢?
在我的代码片段中,我没有使用new
。因此,我的对象的生命周期由大括号控制。
在您的代码片段中,您确实使用了 new
。因此,对象的生命周期由 delete
.
的使用控制
当然,你忘了使用 delete
,所以这就是你的对象从未被破坏的原因(除非你的整个程序退出)。
其他人注意到现代 C++ 提供了改进的 new
替代方案,您应该在大多数情况下使用它们。您可以阅读他们的答案。然而,从机械上讲,理解普通 new
的作用以及 delete
如何与之配对仍然很有帮助。
手动调用析构函数
您几乎可以肯定不必担心这一点,因为手动调用析构函数的情况很少见且高级。基本上,如果您自己管理存储对象的内存(您几乎从不这样做,但也有极少数例外),那么编译器无法判断何时析构,因此您必须告诉它何时析构。有关典型的深奥示例,请参阅 this。
只有指针需要调用析构函数来删除它们或关闭程序
本质上,如果我创建一个新的 class 的多个实例,我是否需要为每个实例调用析构函数,或者在每个实例销毁后调用它(如果我使用 [=,我深表歉意) 21=] 个术语,constructors/destructors 是我还没有完全掌握的概念)。
更具体地说,这是我正在使用的一些代码(如果风格不好,我将不得不再次道歉,我有一个学校问题的想法,想尽快把代码写下来) .
while(read >> f >> l >> t >> s >> sta >> acct >> bal)
{
cout << "test" << endl;
ptr[i] = new account(f,l,t,s,sta,acct,bal);
ptr[i]->printcontents();
cout << "test" << endl;
i++;
cout << i << endl;
}
所以为了这个问题,假设这将循环三次。我是否只需要调用一次 "account" 的析构函数来销毁新帐户的所有三个实例,或者一个调用会离开另外两个?这甚至是一个好习惯吗?
编辑:我注意到我的一些 post 被截断了,所以我添加了最后几行,但人们已经解决了这个问题。我是用户指针的原因纯粹是因为作业要求我这样做;坦率地说,我现在看不到使用它们的意义,但我认为它们会在某个地方变得有用。我还应该补充一点,动态内存分配也应该用于分配。
每个 new
应该用 delete
如果您有一个指针数组,并且每个指针 new
,则每个实例需要 delete
。
另一方面,如果您 new
对象数组,则可以 delete []
整个数组。
附带一点,对于您的代码,而不是使用 ptr
(您没有告诉我们详细信息,请考虑仅使用 std::vector<account>
并使用 push_back
然后它将根据需要自动调整大小,而不是 ptr[i] = new...
.
析构函数会自动调用,您通常不必担心 除非您使用 new
.
在这种情况下,一旦您不再需要分配的每个内存,就必须调用 delete
。
请注意,如果您使用 new []
分配数组,则必须使用 delete[]
进行取消分配:
int *a = new int[10]; // allocating an array of 10 integers
//...
delete[] a; // release memory
在现代 C++ 中,您应该考虑托管指针来完成这项工作。类似于:
while(read >> f >> l >> t >> s >> sta >> acct >> bal)
{
cout << "test" << endl;
ptr[i] = std::make_unique<account>(f,l,t,s,sta,acct,bal);
ptr[i]->printcontents();
cout << "test" << endl;
i++;
cout << i << endl;
}
在这里,std::make_unique
将 return 一个 std::unique_ptr
将在销毁时调用关联内存上的 delete。
最后一点:你确定你真的需要指点吗?从你的例子很难说,但根据你的使用情况,你也可以创建静态分配的对象:
while(read >> f >> l >> t >> s >> sta >> acct >> bal)
{
cout << "test" << endl;
ptr[i] = account(f,l,t,s,sta,acct,bal);
ptr[i].printcontents();
cout << "test" << endl;
i++;
cout << i << endl;
}
通常您必须删除您创建的每个实例。具体怎么做取决于一点……但简单的经验法则:
每次使用 new
都必须使用 delete
。
每次使用 new[]
都必须使用 delete[]
。
如果您从自动声明中获取实例,则无需执行任何操作,因为它将连同其堆栈框架一起销毁;但如果你创造了它,你就摧毁了它。
正如其他人所指出的,如果你使用new
,那么你将需要delete
。但是,您真正的麻烦是概念上的。你问了一个很好的问题 new
和 delete
是外围的。
99.5% 以上的正常使用析构函数是为了让编译器自动调用它们。 (0.5% 的例外是深奥的。我们现在不需要担心这个。)
考虑这个代码片段:
int n = 5;
{
int m = 2;
++m;
n *= m;
// The variable m is automatically destructed here.
}
// Here, n == 15.
看看效果如何? m
的析构函数在 m
到达其生命周期结束时自动调用,这(因为 m
不是用 new
创建的)发生在块的末尾m
被实例化。
当然,m
是一个 int
,因此它的析构函数不执行任何操作(或者,如果您愿意,m
没有析构函数)。您自己定义的其他类型,例如您的类型 account
,可以有析构函数。当单个对象(account
的一个实例)到达其生命周期的尽头时,针对单个对象自动 调用析构函数。
新建和删除
那么,这与new
和delete
有什么关系呢?
在我的代码片段中,我没有使用new
。因此,我的对象的生命周期由大括号控制。
在您的代码片段中,您确实使用了 new
。因此,对象的生命周期由 delete
.
当然,你忘了使用 delete
,所以这就是你的对象从未被破坏的原因(除非你的整个程序退出)。
其他人注意到现代 C++ 提供了改进的 new
替代方案,您应该在大多数情况下使用它们。您可以阅读他们的答案。然而,从机械上讲,理解普通 new
的作用以及 delete
如何与之配对仍然很有帮助。
手动调用析构函数
您几乎可以肯定不必担心这一点,因为手动调用析构函数的情况很少见且高级。基本上,如果您自己管理存储对象的内存(您几乎从不这样做,但也有极少数例外),那么编译器无法判断何时析构,因此您必须告诉它何时析构。有关典型的深奥示例,请参阅 this。
只有指针需要调用析构函数来删除它们或关闭程序