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 ;
}
运行结果:

但是,如果没有默认构造函数,会出现怎么样呢?
看下图报错提示:

那要如何实例化一个没有默认构造函数的对象数组呢?
下面我将介绍两种方法:
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 ;
}
运行结果

通过运行结果可以看出,无论是否有默认构造,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 ;
}
运行结果:

通过运行结果可以看出,无论是否有默认构造,placement new会向已经申请的空间重新构建对象。
C++中若类中没有默认构造函数,如何使用对象数组的更多相关文章
- c++中在一个类中定义另一个只有带参数构造函数的类的对象
c++中在一个类中定义另一个只有带参数构造函数的类的对象,编译通不过 #include<iostream> using namespace std; class A { public: ...
- Java中主类中定义方法加static和不加static的区别
Java中主类中定义方法加static和不加static的区别(前者可以省略类名直接在主方法调用(类名.方法),后者必须先实例化后用实例调用) 知识点:1.Getter and Setter 的应用 ...
- python---Django中模型类中Meta元对象了解
Django中模型类中Meta元对象了解 1.使用python manage.py shell 进入编辑命令行模式,可以直接进入项目(为我们配置好了环境) python manage.py shell ...
- C++学习笔记16,C++11中的显式的默认构造函数以及显示删除默认构造函数
在早期的C++中.假设须要一些接受一些參数的构造函数,同一时候须要一个不接收不论什么參数的默认构造函数.就必须显示地编写空的默认构造函数.比如: //tc.h class A{ private: in ...
- 【Java基础之Object类(一)】Java中Object类中的所有方法(toString、equals、hashCode、clone、finalize、wait和notify等)详解(转载)
java中的hashcode.equals和toString方法都是基类Object的方法. 首先说说toString方法,简单的总结了下API说明就是:返回该对象的字符串表示,信息应该是简明但易于读 ...
- 转载:java 中对类中的属性使用set/get方法的意义和用法
经常看到有朋友提到类似:对类中的属性使用set/get方法的作用?理论的回答当然是封闭性之类的,但是这样对我们有什么作用呢?为什么要这样设计?我直接使用属性名来访问不是更直接,代码更简洁明了吗?下面我 ...
- python中的类中属性元素加self.和不加self.的区别
在类中,self只能在函数中使用,表示的是实例属性,就是每个实例可以设置不值,而不相互影响.如果在类级别使用没有self的属性,是类属性,一般作为全局变量来用的.事实上:就是一个是类属性 一个是对象属 ...
- 4. 在Inspector面板中显示类中变量+ 拓展编辑器
1. C#脚本如下: using UnityEngine; using System.Collections; public class MyTest : MonoBehaviour { ; ; [S ...
- java中File类中list()和listFiles()方法区别
list()和listFiles()方法区别: 1.返回值类型不同:前者为String数组,后者为File对象数组 2.数组中元素内容不同:前者为string类型的[文件名](包含后缀名),后者为Fi ...
随机推荐
- Step-by-step from Markov Process to Markov Decision Process
In this post, I will illustrate Markov Property, Markov Reward Process and finally Markov Decision P ...
- Netty之大名鼎鼎的EventLoop
EventLoopGroup 与Reactor: 前面的章节中我们已经知道了,一个Netty 程序启动时,至少要指定一个EventLoopGroup(如果使用到的是NIO,通常是指NioEventLo ...
- Python 学习笔记17 文本 - 读写
在我们的编程过程中,我们经常需要对文件进行读写操作. 在Python中,对文本的读写非常的方便,只需要简单的几行代码就可以实现. 我们首先新建一个文本文件"Text.txt", 里 ...
- Linux服务器安全配置小结(转)
众所周知,网络安全是一个非常重要的课题,而服务器是网络安全中最关键的环节.Linux被认为是一个比较安全的Internet服务器,作为一种开放源代码操作系统,一旦Linux系统中发现有安全漏洞,Int ...
- C# 对象转JSON字符串
对象转JSON字符串 /// <summary> /// 对象转Json字符串 /// </summary> /// <param name="obj" ...
- 让centos使用ubuntu的make命令补全功能
一直习惯使用debian.ubuntu做开发机,最近it要求各种安全加固,且只提供centos自动化脚本,而ubuntu版本比较乱,14.16.17都要自己整一遍太麻烦,索性换装centos7. 换了 ...
- 用vbs脚本简易实现 番茄工作法
番茄工作法: 专注于某一段时间,减少打断,提高时间的感知和掌控. 25min工作+5min休息 周期:4x(25+5)+20 VBS代码实现如下: Dim fso,f,count,time,shell ...
- c语言开发浏览器插件
c语言开发浏览器插件 senk????sec???
- Sass--混合宏 VS 继承 VS 占位符
什么时候用混合宏,什么时候用继承,什么时候使用占位符?”其实他们各有各的优点与缺点,先来看看他们使用效果: a) Sass 中的混合宏使用 总结:编译出来的 CSS 清晰告诉了大家,他不会自动合并相同 ...
- golang-练习3
题目:将输入的字母变成其下一个字母,并且元音字母大写 package main import "fmt" func LetterChanges(str string) string ...