动态创建类数组,同时调用类的构造函数
这是我铁哥们gwx的blog,挂在我这里让我瞻仰瞻仰 😍
这可比我的哪些垃圾blog有价值多了 😭😭
在写代码的过程中我们经常会遇见这样的问题
#include <iostream>
#include <cstdlib>
#include <new>
using namespace std;
class test
{
public:
int data;
test(int n)
{
cout << "构造:";
data = n;
cout << n << endl;
}
~test(){ cout << "析构:" << data << endl;}
};
int main()
{
test * a;
a=new test[10];//这里想要让a[i]依次调用test(2*i)但是会报错
return 0;
}
导致报错的问题,主要原因是类没有默认的构造函数,而我们又希望在构建类数组的时候给它传递一些动态变化的参数该怎么办,以下有三种方法:
1 认怂
没错,既然实现不了就认怂呗,将构造函数的功能分开。先写一个默认构造函数,然后再用其他成员函数实现功能。如下:
#include <iostream>
#include <cstdlib>
#include <new>
using namespace std;
class test
{
public:
int data;
test(){};
void func(int n)
{
cout << "func:";
data = n;
cout << n << endl;
}
~test(){ cout << "析构:" << data << endl;}
};
int main()
{
test * a;
a=new test[10];
for(int i=0;i<10;i++)
a[i].func(i*2);
delete [] a;
return 0;
}
2 指针
但是我们怎么能让这种东西打败,聪明的你一定想到还有另一种方法,就是创建一个指针数组。然后再动态的给指针数组构造对象。如下:
#include <iostream>
#include <cstdlib>
#include <new>
using namespace std;
class test
{
public:
int data;
test(int n)
{
cout << "func:";
data = n;
cout << n << endl;
}
~test(){ cout << "析构:" << data << endl;}
};
int main()
{
test ** a;
a=new test*[10];
for(int i=0;i<10;i++)
a[i]=new test(i*2);
for(int i=0;i<10;i++)
delete a[i];
delele a;
return 0;
}
这样的方法确实能够解决问题,但是还存在一些问题。这种方法并没有创建一个真正的数组,而是创建了指针的数组,实际上多浪费了一个指针数组的空间,同时如果用
sizeof(a[0]);
这样的函数并不会得到a[0]的大小,而是得到一个指针的大小。
3 定位new
第三种方案就是使用定位new。(需要包含new头文件)
在讲解定位new之前,我们先来看看new是怎么工作的。
new诞生的原因就是因为c语言的malloc在面对类的构造函数有点力不从心。malloc的作用仅仅是分配空间。
(test *)malloc(sizeof(test));
实际上没有调用test类的构造函数,仅仅只是创建了一个test大小的内存空间而已。而new实际上有两个功能,第一个和malloc一样:向操作系统申请空间,而第二个则是调用对象的构造函数。
而定位new是则是给new加了一个功能,就是在你指定的空间中new一个对象。也就是不向操作系统申请空间,直接在指定的地址调用对象的构造函数。定位new的使用方法
new(指定的地址) test(i);
现在这个问题就简单了,只需要我们申请一块空间,然后用定位new调用构造函数即可。
#include <iostream>
#include <cstdlib>
#include <new>
using namespace std;
class test
{
public:
int data;
test(int n)
{
cout << "构造:";
data = n;
cout << n << endl;
}
~test(){ cout << "析构:" << data << endl;}
};
int main()
{
test *ptr;
int size = 10;
test *buffer = (test *)malloc(size * sizeof(test));
for (int i = 0; i < 10; i++)
{
new (buffer + i) test(i * 2);
}
ptr = buffer;
for (int i = 0; i < 10; i++)
{
ptr->~test();
ptr++;
}
free(buffer);
return 0;
}
这里先用malloc创建了数组的空间,然后用new调用了构造函数,最后用指针调用对象的析构函数,同时free掉创建的空间。