结论:当对象(内存空间)初始化或者被销毁的时候,编译器才会调用构造和析构函数
指针也就是地址。通过指针可以访问到内存,从而可以访问到里面的内容。
通过变量名可以访问内存空间里的内容。
变量就是一段内存空间,它包括里面存的内容以及地址。
class Person {
private:
int age;
public:
Person() {
cout << "无参构造" << endl;
}
Person(int n) {
age = n;
cout << "有参构造" << endl;
}
Person(const Person& p) { //只用引用方式传递对象,使用const防止对象被改变
age = p.age;
cout << "拷贝构造" << endl;
}
~Person() {
cout << "析构函数" << endl;
}
};
Person toM() {
Person p;
cout << "地址是" << (int)&p << endl;
return p; //它返回了一个Person对象,
//但是跟p是不同的,相当于重新创建了一个Person对象用于返回
}
void test09() {
Person p1 = toM(); //以值方式返回局部对象
cout << "地址是" << (int)&p1 << endl;
cout << "地址是" << (int)&p1 << endl;
}
int main(){
test09();
return 0;
}
打印结果是:
无参构造
地址是-1614875116
地址是-1614875116
地址是-1614875116
析构函数
请按任意键继续. . .
当我们更改一部分代码,看一下结果
Person toM() {
Person p;
Person p2;
Person p3;
cout << "地址是" << (int)&p << endl;
return p; //它返回了一个Person对象,
//但是跟p是不同的,相当于重新创建了一个Person对象用于返回
}
void test09() {
Person p1 = toM(); //以值方式返回局部对象
cout << "地址是" << (int)&p1 << endl;
cout << "地址是" << (int)&p1 << endl;
}
输出:
无参构造
无参构造
无参构造
地址是-769984828
析构函数
析构函数
地址是-769984828
地址是-769984828
析构函数
请按任意键继续. . .
对比上面两个代码,我们可以发现,调用无参构造是在toM函数中的。我们没有用return返回对象的时候,比如p2,p3,在toM结束后便调用了析构函数。但是用return返回的p并没有调用析构函数,因为此时对象p所对应的内存空间并没有被释放,而是被返回后用到了别处(参考本文第一行结论)。
同理:Person p1 = toM()虽然看上去像定义了一个对象,但是实际上并没有开辟新的内存空间,所以也不需要初始化内存空间,所以此时不会调用构造函数(这也就是第一个输出只有一个构造函数的原因),这一行代码只是用p1去接收了这个原来已经定义过的内存空间。
当test09()结束的时候刚开始p对应的内存空间(也就是后来p1对应的内存空间才被销毁)此时才会调用析构函数。
但是当使用int进行测试的时候发现有问题:
#include<iostream>
using namespace std;
int test() {
int p;
int w;
cout << "w对应的地址" << (int)&w << endl;
cout << "p对应的地址" << (int)&p << endl;
return p;
}
int main() {
int k = test();
int s = test();
cout << "s的地址" << (int)&s << endl;
cout << "k的地址" << (int)&k << endl;
system("pause");
return 0;
}
输出:
w对应的地址-187696620
p对应的地址-187696652
w对应的地址-187696620
p对应的地址-187696652
s的地址-187696300
k的地址-187696332
请按任意键继续. . .
此时,输出的地址又不一样了,让我纠结了很久,突然灵感爆发。
我猜想,因为自定义类并没有回收内存空间的功能,而int有回收内存的功能,所以导致了不同,只能这样理解了,等后续再学学。反正自定义的类跟int是不一样的就对了。
破案了:问了chatgpt,是因为移动语义优化,移动语义的优化通常是由编译器自发进行的,这是C++11引入的一个重要特性。移动语义允许在不复制数据的情况下将资源从一个对象转移到另一个对象,从而提高程序性能。!!!!!!