2017-08-04 37 views
1

我正在阅读第二版C++:初学者指南作者:Herbert Schildt通过第一个对象在C++中创建第二个对象时,第一个对象的位置在哪里?

模块9.4,他谈到返回对象:

就像对象可以传递给函数,函数可以返回的对象。要返回一个对象,首先声明 该函数返回一个类的类型。其次,使用正常返回 声明返回该类型的对象。以下程序有一个名为mkBigger()的成员函数。它返回一个对象,其值为调用对象的值的两倍。

这是“下面的程序”,他提到:

// Returning objects. 
#include <iostream> 
using namespace std; 

class MyClass { 
int val; 
public: 
    // Normal Constructor. 
    MyClass(int i) { 
     val = i; 
     cout << "Inside constructor\n"; 
    } 

    ~MyClass() { 
    cout << "Destructing\n"; 
    } 

    int getval() { return val; } 

    // Return an object. 
    MyClass mkBigger() { 
     Myclass o(val * 2); // mkBigger() returns a MyClass object. 

     return o; 
    } 
}; 

void display(MyClass ob) 
{ 
    cout << ob.getval() << '\n'; 
} 

int main() 
{ 
    cout << " Before Constructing a.\n"; 
    MyClass a; 
    cout << "After constructing a.\n\n"; 

    cout << "Before call to display.\n"; 
    display(a); 
    cout << "After display() returns.\n\n"; 

    cout << "Before call to mkBigger().\n"; 
    a = a.mkBigger(); 
    cout << "After mkBigger() returns.\n\n"; 

    cout << "Before second call to display.\n"; 
    display(a); 
    cout << "After display() returns.\n\n"; 

    return 0; 
} 

这给了我们以下的输出:

Before Constructing a. 
Inside constructor 
After constructing a. 

Before call to display. 
10 
Destructing 
After display() returns. 

Before call to mkBigger() 
Inside constructor 
Destructing 
Destructing 
After mkBigger() returns. 

Before second call to display. 
20 
Destructing 
After display() returns. 

Destructing 

Schildt然后继续解释说,原因有两个“在mkBigger()调用期间“破坏”消息是因为以下事实:

当函数返回一个对象时,会自动创建一个临时对象,该临时对象将保存返回值。这个对象实际上是由函数返回的。该值返回后,该对象被销毁。

我真的很惊讶没有'Destructing'消息。我遇到以下问题:给定mkBigger()的定义,将创建一个新的MyClass实例,并且该实例返回并放置在地址a中。因此,在做

a = a.mkBigger(); 

我的印象时,因此,原来的对象之前举行一个一个不再引用。它是否正确?如果是这样,那么我有以下问题:

有人告诉我C++有一些垃圾收集的一些概念。这个物体会被垃圾收集吗?这个对象现在在哪里?这是许多人在谈论C++的“危险”时提到的可能令人担忧的内存泄漏的例子吗?

+5

我强烈建议您从Schildt的作品中更好地学习C++。另外,如果你打算使用析构函数,你也应该使用复制构造函数和赋值运算符。 –

+1

如[这些]之一(https://stackoverflow.com/a/388282/6525260)也许? –

+0

我其实碰到很多人批评他的书,同时试图找到我的问题的答案。我会寻找一本更好的书。 – Devilius

回答

3

mkbigger()中的一个析构函数在o上调用,MyClass实例通过值传入;它在函数结束时超出了范围。另一个是在o被销毁时返回的临时副本。还有什么不在范围之内?不是a in main();因此你不应该期望第三个析构函数被调用。自动对象超出范围时,C++不会在调用析构函数之外提供垃圾回收。

与其他一些现代语言不同,a不“持有对象的引用”; a的对象,因为它是一定数量的字节保存原始数据成员。当您执行a = a.mkBigger();时,MyClass的默认赋值运算符被调用,该运算符仅将右侧临时对象内的val复制到a中的val,覆盖已存在的值。如果val是公开的,则a = a.makeBigger()将等于a.val = a.makeBigger().val

当您使用new分配内存,然后无法使用delete取消分配该内存时,会发生内存泄漏。对于内部执行此操作的类,您必须至少编写自己的拷贝构造函数,赋值操作符和析构函数。

+0

Ahhhh,这使得很多意义。非常感谢你! – Devilius

相关问题