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

问题描述:

这两个实例化和方法调用类型有什么区别?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; 
} 

从什么IVE读,使用所述第一方式中,变量是在堆上分配,并且第二,在堆栈中,但的arent两者Main范围内,并在函数退出后解除分配?

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

+0

感谢编辑@remyabel,这种方式更好,它避免了混淆。 – Leandragem 2014-11-05 00:02:11

+0

你似乎对C++的理解很少。在问这样的超级基本问题之前,你应该先做一些研究或读一本书。这是C++ 101 – Falmarri 2014-11-05 00:02:59

+0

那么你是对的。我是C++的新手,但在继续下一步之前,我试图更好地理解这些主题。你会推荐一个很好的C++阅读材料吗? – Leandragem 2014-11-05 00:04:18

您的权利这两个变量都在Main范围和功能退出后释放,但在第一种情况下它是Test*值被释放,而不是Test实例本身。一旦指针解除分配,类实例就会泄露。在第二种情况下,Test实例位于堆栈上,因此实例本身已解除分配。

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

除非超载,foo->bar相当于(*foo).bar。调用语法不同,因为在第一种情况下,test1是指向实例的指针,而第二种情况下,test2是一个实例。

但不是都在主范围内,并在 函数退出后被释放?

完全没有...... * test1在你调用delete之前不会被释放。

+0

你不是指'test1'吗? – 2014-11-05 00:02:50

但都没有在主范围内,并在函数退出后被释放?

随着作用域关闭并释放,栈实例解除展开。指针也是,但它指向的对象不是。您必须明确delete实例分配与new

在第一个示例中,您正在创建一个指向堆栈上的对象的指针,以及堆中的对象本身。

在第二个示例中,您正在堆栈上创建对象本身。

语法区别是通过指针调用函数并直接在对象上调用函数的区别。

对于正在清理的第一个示例,在指针超出范围之前需要一个delete或者出现所谓的内存泄漏,这是错误的。当程序退出时,操作系统会清理内存泄漏,但最好的做法是避免它们。

+0

感谢您的回复。对此有没有“最佳实践”?像什么时候使用一个或另一个? – Leandragem 2014-11-05 00:06:37

+2

@Leandragem使用本地(堆栈)对象,除非您需要该对象的生存期超出当前块的存在,或者如果您将该对象的所有权传递给其他人。或者有时如果你需要一个不适合堆叠的大对象或数组,例如数百万的元素。 – 2014-11-05 00:08:38

你已经清楚地说明了你的问题的不同之处,一个在堆栈上,另一个在堆上。是的,当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个“创建新的MemoryLeak”。只有10行“MemoryLeak deleted”行。所以其他10个实例仍然在内存中,直到您关闭程序。现在让我们说,该程序永远不会关闭,并且MemoryLeak具有20个字节的大小。和makeMemoryLeak()每分钟运行一次。在一天或1440分钟后,您将拥有28.125 kb的内存,但您无法访问。

的解决办法是改变makeMemoryLeak()

void makeMemoryLeak(){ 
    MemoryLeak mem1; 
    MemoryLeak* mem2 = new MemoryLeak(); 
    delete mem2; 
} 

关于什么被创建和销毁:

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) 
+0

因为你正在退出main,* test2 **被**销毁。只要您退出程序,操作系统就会清理所有分配的内存。如果你做了类似于我的答案的东西,那就表明它没有被删除。 – David 2014-11-05 00:31:06

+0

@大卫这是一个很好的观点。相应的更改。 – Galik 2014-11-05 01:34:23

,如果你不出来的主之前删除的Test1(测试*),就会造成内存泄漏。