C ++中的对象实例化方法

时间:2014-11-04 23:57:36

标签: c++

这两个实例化和方法调用类型之间有什么区别?

以此代码为例:

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>

此外,两个示例中的调用方法都不同,为什么

7 个答案:

答案 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 *),则会导致内存泄漏。