C++当函数返回值为类类型时 作为左值的疑问

#include
using namespace std;

//定义类

class Person
{
private:
int m_Age;
public:

//定义默认构造函数

Person()

{

cout << "默认构造函数!" << endl;

}

//定义有参构造函数
Person(int age)
{
    m_Age = age;

    cout << "有参构造函数!" << endl;
}

//定义拷贝构造函数

Person(const Person& p)

{

m_Age = p.m_Age;

cout << "拷贝构造函数!" << endl;
}
~Person()
{
    cout << "析构函数!" << endl;
}

};

//定义返回值为Person的函数

Person func()

{

Person p(10);

return p;

}

int main()

{

func()= 10;//调用func函数,并将它的返回值作为左值
system("pause");
return 0;

}

我用的vs2019

输出结果为:

有参构造函数!

有参构造函数!

拷贝构造函数!

析构函数!

析构函数!

析构函数!

这是为什么?

还有就是返回值作为左值的问题,c++提供的默认数据类型作为返回值时
不能作为左值,用户自定义数据类型可以,有什么要求和注意事项吗?

首先,你的程序能正常运行,你可以debug运行,将func() = 10;设断点,然后F11逐语句执行。
系统先执行的是Person func(),声明一个Person类的对象,因为赋值10,所以系统判定为你声明的对象会调用Person::Person(int age)构造该对象,所以会先输出“有参构造函数!”。
接下来系统会执行func()本身,其中Person p(10);又声明了一个Person类的对象,输出“有参构造函数!”
语句return p;会将对象p拷贝输出,会调用Person(const Person& p)构造一个Person对象,输出“拷贝构造函数!同时析构对象p,输出一个“析构函数!”。
该对象返会后,会再次被右值赋值。
当Person func()执行完成后,剩下的两个对象都不再有存在的必要,系统则调用每个对象的析构函数,所以会输出再输出两个“析构函数!”。
如果你想看一下析构的顺序,可以在Perseon类中增加一个变量做为不同构造函数的标志加以保存,对象析构时输出,就可以判断析构的顺序了。
关于函数返回值做为左值的问题,本例中返回值是一个类的对象,用于函数返回的是一个引用,是可以做为左值使用的。更详细的解答,请参见(不是我写的,为了表示尊重原作者,只能给你发个链接)https://blog.csdn.net/sunshinewave/article/details/7830701?utm_source=blogxgwz9
若有问题,再讨论。
下面是修改后的测试代码:

#include <iostream>

using namespace std;

//定义类

class Person
{
private:
    int m_Age;
public:

    //定义默认构造函数

    Person()

    {
        m_Age = 0;
        cout << "默认构造函数!" << endl;
        cout << this << endl;   // 输出该对象的指针                     
        cout << "m_Age = " << m_Age << endl << endl;
    }

    //定义有参构造函数
    Person(int age)
    {

            m_Age = age;
        cout << "有参构造函数!" << endl;
        cout << this << endl;   // 输出该对象的指针 
        cout << "m_Age = " << m_Age << endl<< endl;

    }
    //定义拷贝构造函数

    Person(const Person& p)

    {

        m_Age = p.m_Age;
        cout << "拷贝构造函数!" << endl;
        cout << this << endl;   // 输出该对象的指针 
        cout << "m_Age = " << m_Age << endl<<endl;
    }
    ~Person()
    {
        cout << this << endl;   // 输出该对象的指针 
        cout << "析构函数!" <<"   "<<m_Age<<endl;
    }
};

//定义返回值为Person的函数

Person func()

{

    Person p(10);

    return p;
}




int main()
{
    func() = 20;//调用func函数,并将它的返回值作为左值,为了区别p(10),令func() = 20;
        system("pause");
}

运行输出:

有参构造函数!
00EFF898
m_Age = 20

有参构造函数!
00EFF85C
m_Age = 10

拷贝构造函数!
00EFF8A4
m_Age = 10

00EFF85C
析构函数! 10
00EFF8A4
析构函数! 20
00EFF898
析构函数! 20
请按任意键继续. . .

func()= 10;
->
Person p = func();
p = 10;
这样看看。有些编译器不支持。

如果返回值是默认的数据类型,是不能作为左值的,必须做左值的话,只能返回引用类型。
如果返回值是自定义类型,若是const定义就不能作为左值,其他的都可以做左值,当左值是类类型时,必须调用成员函数才可以

你这个代码,真难看懂
返回值赋值一般除了引用,其他的要不报错, 要不无意义