4.类和对象(上)
构造函数不写的话编译器自动生成无参构造函数,对于成员变量有内置类型,不写 行为是不确定的不一定初始化,自定义类型只能调用默认构造函数。构造函数大多数都要自己写,像myqueue不用谢,析构函数和构造函数类似不写编译器自动生成。内置类型也是。。。自定义类型也是。。。但是有些类不需要清理不需要析构像是日期类,myqueue也不用,因为这是自定义类型,自己调用栈析构。构造也是。栈有资源需要释放,所以栈需要,。
可以用同类型d1初始化,这叫拷贝构造
#include<iostream>
using namespace std;
class Date
{
public:Date(int year = 1, int month = 1, int day = 1){_year = year;_month = month;_day = day;}error C2652: “Date”: 非法的复制构造函数: 第一个参数不应是“Date”Date d2(d1)Date(const Date& d){_year = d._year;_month = d._month;_day = d._day;}
传值C++规定函数传值传参要调用拷贝构造,
如果是C语言,整形按四个字节拷贝过去,C++规定必须调用拷贝构造函数,所以运行这一行43,先执行传参:拷贝构造,执行完了回来,再执行函数体,相当于两个函数。
但是我本身就要调用拷贝构造的话,我先传参,传参会形成新的拷贝构造,新的拷贝构造完成了,那么继续走,这个新的拷贝构造又调用新的函数,拷贝构造先传参又形成新的。。。。红线是传参,虚线是调用拷贝回来
如果我用了引用,传参不会形成拷贝构造
因为d是d1别名,顺畅的回来了,没有形成新的拷贝构造,
加引用就建议把const加上,const可以保证形参不被改变,例如:不小心写错==,我去初始化你,自己还被改了,不合理
所以加上const
d就是d1,this就是d2
所以这里自定义类型还建议传值传参吗,因为还要调用拷贝构造太麻烦,内置类型影响不是很大, 自定义类型传引用并且加const所以日期类不惜要写拷贝构造
如果不写拷贝构造,会完成浅拷贝,但是程序崩了,
a应该是拷贝空间拷贝值
typedef int STDataType;
class Stack
{
public:Stack(int n = 4){_a = (STDataType*)malloc(sizeof(STDataType) * n);if (nullptr == _a){perror("malloc申请空间失败");return;}_capacity = n;_top = 0;}// st2(st1)Stack(const Stack& st){cout << "Stack(const Stack& st)" << endl;// 需要对_a指向资源创建同样大的资源再拷贝值_a = (STDataType*)malloc(sizeof(STDataType) * st._capacity);if (nullptr == _a){perror("malloc申请空间失败!!!");return;}memcpy(_a, st._a, sizeof(STDataType) * st._top);_top = st._top;_capacity = st._capacity;}void Push(STDataType x){if (_top == _capacity){int newcapacity = _capacity * 2;STDataType* tmp = (STDataType*)realloc(_a, newcapacity *sizeof(STDataType));if (tmp == NULL){perror("realloc fail");return;}_a = tmp;_capacity = newcapacity;}_a[_top++] = x;}~Stack(){cout << "~Stack()" << endl;free(_a);_a = nullptr;_top = _capacity = 0;}
private:STDataType* _a;size_t _capacity;size_t _top;
};int main()
{Stack st1;st1.Push(1);st1.Push(2);// Stack不显示实现拷贝构造,用自动生成的拷贝构造完成浅拷贝// 会导致st1和st2里面的_a指针指向同一块资源,析构时会析构两次,程序崩溃Stack st2(st1);return 0;
}
C++,传值传参为什么调用拷贝构造:如果是C语言,我的栈传给你,咱两指向一块资源,里面影响外面,另外你destroy,我destroy不行
C++真要传值传参 这样更合理
此时st是st1的深拷贝,值互不影响,他析构也不影响我,更合理
自定义类型用传值传参不好,因为本来里面啥事不干,拷贝构造代价很大,除了直接赋值还要去栈堆开空间,所以用引用和const
myqueue不用构造不用析构不用拷贝构造,全靠栈的
如果实现了析构说明有资源要清理,那么基本上就需要拷贝构造
这样写也可调用拷贝构造
如果不想让这个拷贝发生,加一个引用
返回前调用了析构
这个警告是从底部去看的,引用就是地址
这样是正确的,出了作用域st还在,这是静态对象,就可以用引用返回,减少拷贝