当我调用一个简单的函数时,析构函数被调用

Posted

技术标签:

【中文标题】当我调用一个简单的函数时,析构函数被调用【英文标题】:Destructor gets called when I call a simple function 【发布时间】:2016-01-11 09:51:14 【问题描述】:

我做了一个简单的程序来创建一个类,它是 3 个对象。我重载了 =、+= 和

据我所知,在对象超出范围或使用“删除”运算符时会调用析构函数。但是,就我而言,两者都不是。我查看了其他一些网站,例如the oficial C++ website,但是,我无法得到答案。这是我写的代码。

#include<iostream>
using namespace std;

class Class

    int flag,name;
public:
    Class(int y,int z)

    flag=y;
    name=z;


    Class& operator=(Class);
    Class operator+=(Class);
    friend ostream& operator<<(ostream&,Class&);    

    ~Class()

    cout<<"Destroying "<<flag<<endl;

;

int main()

    Class C1(1,80),C2(2,90),C3(3,100);
    cout<<C1<<C2<<C3<<endl;
    C1=C2=C3;
    cout<<C1<<C2<<C3<<endl;
    C3=C1+=C2;
    cout<<C1<<C2<<C3<<endl;
    return 0;


Class& Class::operator=(Class x)

    name=x.name;
    return *this;


Class Class::operator+=(Class x)

    name+=x.name;
    return *this;


ostream& operator<<(ostream& o,Class& c)

    o<<c.name;
    return o;

我得到的输出是这样的:

8090100
Destroying 2
Destroying 3
100100100
Destroying 1
Destroying 2
200100200
Destroying 3
Destroying 2
Destroying 1

C2,C3 和 C1,C2 的析构函数在进程中被调用,即使它们没有超出范围。我通过更改函数名称甚至将返回类型更改为“void”来尝试该程序,但仍然调用了析构函数。我在 GCC-4.9.3 中编译了这个程序。

如果我的问题太愚蠢,我将不胜感激。如果我的问题太愚蠢,请原谅我。

【问题讨论】:

我打赌你认为flag 有一个独特的价值,因为你构建了三个具有不同标志的对象。 错误错误错误!编译器通常可以创建临时文件,默认情况下复制每个字段包括“唯一值”。 被销毁的对象不是您的 C1、C2、C3 变量,而是它们的临时副本。添加显式复制构造函数并从中打印诊断信息。还可以使用一些静态计数器并在构造函数中递增它来枚举对象——然后你会看到哪些对象被销毁以及何时被销毁。 您的flag 想法是错误的。只需将您的输出语句更改为:cout&lt;&lt;"Destroying " &lt;&lt; this &lt;&lt; endl; - 然后您会看到那些被销毁的对象是您没有考虑的对象,即临时对象。 【参考方案1】:

您的运算符按值获取参数,制作一个副本,该副本将在函数结束时被破坏。

如果您不想创建副本,请通过 const 引用获取参数。正如interjay 指出的那样,operator+= 也应该返回一个引用而不是复制*this

Class& operator=(const Class&);
Class& operator+=(const Class&);

【讨论】:

operator+= 还应该返回一个引用以避免创建另一个副本。【参考方案2】:
Class& Class::operator=(Class x);

C1=C2=C3;

当您执行C2 = C3 时,请注意operator= 按值取右侧,因此会创建C3 的副本(x);它的数据被复制到C2's。当函数operator= 返回时,参数x 超出范围并被销毁。这种情况发生了两次:一次用于C2=C3,一次用于C1=C2,所以你会看到两者。这也解释了operator+= 的行为。

如果您想避免这种情况,请参考 x,如 Tartan 的回答所示。

【讨论】:

【参考方案3】:

请参考Class&amp; operator=(Class);Class operator+=(Class); 他们将对象作为参数(不是引用)。因此,销毁这些临时对象会调用析构函数。

刚刚注意到上面有更多的 cmets 对此进行了解释... :)

【讨论】:

以上是关于当我调用一个简单的函数时,析构函数被调用的主要内容,如果未能解决你的问题,请参考以下文章

C++ 析构函数何时被调用?

C++ 析构函数何时被调用?

为啥C++里面,析构函数会被调用两次

unity c#怎么调用析构函数

析构函数小结

c++ 析构函数 是在啥时候执行