C++中若类中没有默认构造函数,如何使用对象数组

时间:2023-03-10 06:12:22
C++中若类中没有默认构造函数,如何使用对象数组

前言:

如果定义一个类,有其默认的构造函数,则使用new动态实例化一个对象数组,不是件难事,如下代码:

 #include <memory>
#include <iostream> using namespace std; class Animal
{
public:
#if 1 //用于后面演示,无默认构造函数
Animal() : num()
{
cout << "Animal constructor default" << endl;
}
#endif
Animal(int _num) : num(_num)
{
cout << "Animal constructor param" << endl;
} ~Animal()
{
cout << "Animal destructor" << endl;
} void show()
{
cout << this->num << endl;
} private:
int num;
}; int main()
{
Animal *ani = new Animal[]; delete[]ani; system("pause");
return ;
}

运行结果:

C++中若类中没有默认构造函数,如何使用对象数组

但是,如果没有默认构造函数,会出现怎么样呢?

看下图报错提示:

C++中若类中没有默认构造函数,如何使用对象数组

那要如何实例化一个没有默认构造函数的对象数组呢?

下面我将介绍两种方法:

    1. 使用C++11新特性allocator类

    2. 使用placement new 即operator new(第三个重载版本)void* operator new(size_t  size, void *p)函数

一、allocator类

对于allocator类,请看 我的另一篇blog   http://www.cnblogs.com/SimonKly/p/7819122.html

请看一下代码关于使用如何实现无默认构造函数,动态实例化对象数组的allocator方法

 //#include "CAnimal.h"
#include <memory>
#include <iostream> using namespace std; class Animal
{
public:
#if 1 //即使为0,没有默认构造也是可以,
Animal() : num()
{
cout << "Animal constructor default" << endl;
}
#endif
Animal(int _num) : num(_num)
{
cout << "Animal constructor param" << endl;
} ~Animal()
{
cout << "Animal destructor" << endl;
} void show()
{
cout << this->num << endl;
} private:
int num;
}; /*
由于allocator将内存空间的分配和对象的构建分离
故使用allocator分为以下几步:
1.allocator与类绑定,因为allocator是一个泛型类
2.allocate()申请指定大小空间
3.construct()构建对象,其参数为可变参数,所以可以选择匹配的构造函数
4.使用,与其它指针使用无异
5.destroy()析构对象,此时空间还是可以使用
6.deallocate()回收空间
*/ int main()
{
allocator<Animal> alloc; //1.
Animal *a = alloc.allocate(); //2. //3.
alloc.construct(a, );
alloc.construct(a + );
alloc.construct(a + , );
alloc.construct(a + );
alloc.construct(a + , ); //4.
a->show();
(a + )->show();
(a + )->show();
(a + )->show();
(a + )->show(); //5.
for (int i = ; i < ; i++)
{
alloc.destroy(a + i);
}
//对象销毁之后还可以继续构建,因为构建和内存的分配是分离的
//6.
alloc.deallocate(a, ); cin.get();
return ;
}

运行结果

C++中若类中没有默认构造函数,如何使用对象数组

通过运行结果可以看出,无论是否有默认构造,allocator会选择出最匹配的构造函数(重载)

二、placement new

函数原型:

void* operator new(size_t size, void* p) throw();

函数执行忽略size,只返回p指针,不分配内存。

placement new具体的用法和相关技术点,请参看我的另一篇博文的第三节

http://www.cnblogs.com/SimonKly/p/7826651.html

具体实现:C++中若类中没有默认构造函数,如何使用对象数组??

请看下面的代码:

 #include <iostream>

 using namespace std;

 class animal
{
public:
#if 1 //用于后面演示,无默认构造函数
animal() : num()
{
cout << "animal constructor default" << endl;
}
#endif
animal(int _num) : num(_num)
{
cout << "animal constructor param" << endl;
} ~animal()
{
cout << "animal destructor" << endl;
} void show()
{
cout << this->num << endl;
} void * operator new(size_t size, void *p)
{
return p;
} private:
int num;
}; int main(int args, char ** argv)
{
// 一个动态animal数组
void *p = operator new( * sizeof(animal)); // 申请缓冲器
animal *a = static_cast<animal *>(p); // 转换类型 // 2.对象构建
for (int i = ; i < ; i++)
{
new(a + i) animal(i);// 调用重载构造
}
new(a + ) animal; // 也可以调用默认构造 // 3.使用
for (int i = ; i < ; i++)
{
(a + i)->show();
} // 4.销毁对象
for (int i = ; i < ; i++)
{
(a + i)->~animal();
} // 5.回收空间
delete[]p; cin.get();
return ;
}

运行结果:

C++中若类中没有默认构造函数,如何使用对象数组

通过运行结果可以看出,无论是否有默认构造,placement new会向已经申请的空间重新构建对象。