函数调用完成返回对象后无法解释析构函数调用

Cannot explain a destructor call after a function call is done returning an object

我尝试了 运行 下面的代码,但我不明白何时以及为什么会在 myA=foo(myOtherB).

行调用析构函数

我的问题是,在 foo 函数 return 的 A 对象之后,从 'input' 复制构造它并打印 A copyctor,operator= 被称为打印 'Aop' 然后析构函数被调用打印 A dtor.

为什么此时调用析构函数而不是在 operator= 调用之前的 return 之后?

我遇到的另一个问题是,如果我使用 return A(2) 而不是 return input 构造函数 A 不会调用打印 A 构造函数...

谁能解释一下?我很抱歉代码有点复杂。

#include <iostream>

using namespace std;

class A
{
    public:
        int x;
        A(){ cout<<"A ctor"<<endl; }
        A(const A& a){cout<<"A copyctor"<<endl; }
        virtual~A(){ cout<<"A dtor"<<endl;} 
        virtual void foo(){ cout<<"Afoo()"<<endl;}
        virtual A& operator=(const A&rhs){cout<<"Aop="<<endl; }
        A(int _x)
        {
            x=_x;
        }
};


class B:public A
{
    public:
         B(){ cout<<"B ctor"<<endl; }

         virtual~B(){ cout<<"B dtor"<<endl; }
         virtual void foo(){ cout<<"B foo()"<<endl; }
    protected:
         A mInstanceOfA; 

};

A foo(A& input)
{ input.foo(); return input; //return A(2); does not call the A constructor } 



int main()
{

    B myOtherB;
    A myA;
    myA=foo(myOtherB); 

}

你returnby value,也就是说你return的值被复制到一个临时对象,一个后来被破坏的对象。

return A();

这叫做most vexing parse
您不是在调用 A 的构造函数(不是创建新实例),而是声明一个 returns A 的函数(阅读 link 以获得进一步且可能更正确的解释)。

您可以通过以下方式调用构造函数:

return A{2};

这称为 Uniform initialization syntax(C++ 11 及更高版本)


A myA;
myA=foo(myOtherB); 

在这种情况下,您首先创建一个新的 A 对象 (myA),然后将该变量分配给 foo 函数的 return 值。
由于第二行,这将调用赋值运算符。
您将 foo return 的值复制到 myA 变量。

当已经创建的myA变量被重新赋值时,旧值将被销毁,从而调用destructor.

我认为你想要的是:

A myA = foo(myOtherB);

I tried running the code below and i do not understand when and why does the destructor get called at the line myA=foo(myOtherB).

由于 RAII.

,析构函数将在主函数的最后一个大括号之前调用

Why is the destructor getting called at this point and not right after the return before the operator= call?

我已经在上面回答了这个问题,对象范围很重要。只要您的对象超出范围,就会调用析构函数。

Another problem i have is that if i use return A(2) instead of return input constructor A does not get called printing A ctor...

A foo(A& input)
{ input.foo(); return input; //return A(2); does not call the A constructor } 

您正在返回一个现有的对象输入,您的函数将其作为引用接收,因此系统无需通过调用构造函数来创建对象。