这两个实例化和方法调用类型之间有什么区别?
以此代码为例:
class Test
{
public:
Test(int nrInstance)
{
std::cout << "Class " << nrInstance << " instanced " << std::endl;
}
~Test() { }
int retornaValue()
{
return value;
}
private:
const int value = 10;
};
int main(int argc, char *argv[])
{
Test *test1 = new Test(1);
Test test2(2);
std::cout << test1->retornaValue() << std::endl;
std::cout << test2.retornaValue() << std::endl;
return 0;
}
从我读过的内容,使用第一种方式,变量在堆中分配,第二种在堆栈中,但不在Main
范围内,并且在函数退出后被解除分配? / p>
此外,两个示例中的调用方法都不同,为什么?
答案 0 :(得分:1)
但不在Main范围内,并在之后被释放 功能退出?
完全没有... * test1在你打电话给delete
之前不会被取消分配。
答案 1 :(得分:1)
你的权利是两个变量都在Main
范围内并在函数退出后解除分配,但在第一种情况下,它是被释放的Test*
值,而不是Test
实例本身。一旦指针被释放,类实例就会泄露。在第二种情况下,Test
实例位于堆栈上,因此实例本身已被释放。
另外,两个例子中的调用方法都不同,为什么?
除非超载,否则foo->bar
相当于(*foo).bar
。调用语法是不同的,因为在第一种情况下,test1
是指向实例的指针,而在第二种情况下,test2
是一个实例。
答案 2 :(得分:1)
但是不在Main范围内,并且在函数退出后被解除分配?
当范围关闭时,堆栈实例展开,因此解除分配。指针也是如此,但它指向的对象不是。您必须使用delete
明确new
个实例。
答案 3 :(得分:1)
在第一个示例中,您将创建指向堆栈上对象的指针,以及堆上的对象本身。
在第二个示例中,您将在堆栈上创建对象。
语法差异是通过指针调用函数和直接在对象上调用函数之间的区别。
对于第一个被清理的示例,你错了,在指针超出范围之前你需要一个delete
,或者你有所谓的内存泄漏。当程序退出时,操作系统将清除内存泄漏,但良好的做法是避免它们。
答案 4 :(得分:1)
你已经清楚地说明了你的问题的不同之处,一个在堆栈上,一个在堆上。是的,当 main()
退出时,它将被取消分配。现在让我们采取不同的方法。
#include <iostream>
using namespace std;
class MemoryLeak{
private:
int m_instance
public:
MemoryLeak(int i) : m_instance(i)
{ cout << "MemoryLeak " << i << " created.\n"; }
~MemoryLeak() { cout << "MemoryLeak " << m_instance << " deleted.\n"; }
};
void makeMemoryLeak(){
static int instance = 0
MemoryLeak mem1(++instance);
MemoryLeak* mem2 = new MemoryLeak(++instance);
}
int main(){
for(int x = 0; x < 10; ++x){
makeMemoryLeak();
cout << endl;
}
cin.get(); // Wait to close
return 0;
}
您将看到20&#34; New MemoryLeak已创建。&#34;但只有10&#34; MemoryLeak被删除&#34;线。所以其他10个实例仍在内存中,直到你关闭程序。现在让我们说该程序永远不会关闭,MemoryLeak的大小为20字节。并且makeMemoryLeak()
每分钟运行一次。在一天或1440分钟后,您将占用28.125 kb的内存,但您无法访问。
解决方案是更改makeMemoryLeak()
void makeMemoryLeak(){
MemoryLeak mem1;
MemoryLeak* mem2 = new MemoryLeak();
delete mem2;
}
答案 5 :(得分:1)
关于创建和销毁的内容:
struct Test {};
void func()
{
// instantiate ONE automatic object (on the stack) [test1]
Test test1;
// Instantiate ONE automatic object (on the stack) [test2]
// AND instantiate ONE object from the free store (heap) [unnamed]
Test* test2 = new Test; // two objects!!
} // BOTH automatic variables are destroyed (test1 & test2) but the
// unnamed object created with new (that test2 was pointing at)
// is NOT destroyed (memory leak)
答案 6 :(得分:0)
如果在退出main之前没有删除Test 1(Test *),则会导致内存泄漏。