通过第一个对象在C ++中创建第二个对象时,第一个对象在哪里?

时间:2017-08-04 15:25:29

标签: c++ object garbage-collection

我目前正在阅读 Herbert Schildt 的第二版 C ++:初学者指南

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

  

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

这是他提到的“以下计划”:

// 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'消息的原因是因为:

  

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

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

a = a.mkBigger();

因此,我的印象是先前在 a 中保存的原始对象不再被 a 引用。它是否正确?如果是这样,那么我有以下问题:

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

1 个答案:

答案 0 :(得分:3)

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

与其他一些现代语言不同,a没有&#34;持有参考&#34;对象; a 对象,因为它是保存原始数据成员的一定数量的字节。执行a = a.mkBigger();时,会调用MyClass的默认分配运算符,只需将右侧临时对象内的val复制到vala内,覆盖已存在的值。如果a = a.makeBigger()是公开的,a.val = a.makeBigger().val将等同于val

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