c++ - C++中通过第一个对象创建第二个对象时,第一个对象到哪里去了?

标签 c++ object garbage-collection

我目前正在阅读 Herbert SchildtC++:初学者指南 第二版。

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

Just as objects can be passed to functions, functions can return objects. To return an object, first declare the function as returning a class type. Second, return an object of that type using the normal return statement. The following program has a member function called mkBigger( ). It returns an object that gives val a value twice as large as the invoking object.

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

// 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() 调用期间出现两条“正在破坏”消息的原因是:

when an object is returned by a function, a temporary object is automatically created, which holds the return value. It is this object that is actually returned by the function. After the value has been returned, this object is destroyed.

我真的很惊讶没有 3 个“破坏”消息。我有以下问题:根据 mkBigger() 的定义,创建了一个新的 MyClass 实例,返回的是该实例并放置在 a 的地址中。因此,当做

a = a.mkBigger();

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

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

最佳答案

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

与其他一些现代语言不同,a不“持有”对对象的引用; a 对象,因为它是保存原始数据成员的一定数量的字节。当你做 a = a.mkBigger(); , MyClass的默认赋值运算符被调用,它只是复制 val在右侧的临时对象内进入 val里面a ,覆盖已经存在的值。 a = a.makeBigger()相当于 a.val = a.makeBigger().val如果val是公开的。

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

关于c++ - C++中通过第一个对象创建第二个对象时,第一个对象到哪里去了?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45510501/

相关文章:

c++ - g++ 中 ">"之前的预期主表达式,但在微软编译器中没有

javascript - 需要在 React Native 中将对象转换为 FlatList 的数组

javascript - 在 React 中使用 map() 遍历嵌套的 Prop

java - 长生命周期对象的大量收集与垃圾收集

Java 垃圾回收 : Does setting 'top of stack' to null in pop() method only GC the reference (not object)?

c++ - 如何在模板类函数中分配结构值?

c++ - 如何在 win32 C++ 中的按钮上显示文本和图标?

java - 如何通过 BeanManager 创建和销毁 CDI (Weld) Managed Beans?

c++ - 变量已在 .obj 中定义,但没有循环包含

Javascript 合并键和值