前言:

如果定义一个类,有其默认的构造函数,则使用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++中若类中没有默认构造函数,如何使用对象数组的更多相关文章

  1. c++中在一个类中定义另一个只有带参数构造函数的类的对象

    c++中在一个类中定义另一个只有带参数构造函数的类的对象,编译通不过 #include<iostream> using namespace std; class A { public:  ...

  2. Java中主类中定义方法加static和不加static的区别

     Java中主类中定义方法加static和不加static的区别(前者可以省略类名直接在主方法调用(类名.方法),后者必须先实例化后用实例调用) 知识点:1.Getter and Setter 的应用 ...

  3. python---Django中模型类中Meta元对象了解

    Django中模型类中Meta元对象了解 1.使用python manage.py shell 进入编辑命令行模式,可以直接进入项目(为我们配置好了环境) python manage.py shell ...

  4. C++学习笔记16,C++11中的显式的默认构造函数以及显示删除默认构造函数

    在早期的C++中.假设须要一些接受一些參数的构造函数,同一时候须要一个不接收不论什么參数的默认构造函数.就必须显示地编写空的默认构造函数.比如: //tc.h class A{ private: in ...

  5. 【Java基础之Object类(一)】Java中Object类中的所有方法(toString、equals、hashCode、clone、finalize、wait和notify等)详解(转载)

    java中的hashcode.equals和toString方法都是基类Object的方法. 首先说说toString方法,简单的总结了下API说明就是:返回该对象的字符串表示,信息应该是简明但易于读 ...

  6. 转载:java 中对类中的属性使用set/get方法的意义和用法

    经常看到有朋友提到类似:对类中的属性使用set/get方法的作用?理论的回答当然是封闭性之类的,但是这样对我们有什么作用呢?为什么要这样设计?我直接使用属性名来访问不是更直接,代码更简洁明了吗?下面我 ...

  7. python中的类中属性元素加self.和不加self.的区别

    在类中,self只能在函数中使用,表示的是实例属性,就是每个实例可以设置不值,而不相互影响.如果在类级别使用没有self的属性,是类属性,一般作为全局变量来用的.事实上:就是一个是类属性 一个是对象属 ...

  8. 4. 在Inspector面板中显示类中变量+ 拓展编辑器

    1. C#脚本如下: using UnityEngine; using System.Collections; public class MyTest : MonoBehaviour { ; ; [S ...

  9. java中File类中list()和listFiles()方法区别

    list()和listFiles()方法区别: 1.返回值类型不同:前者为String数组,后者为File对象数组 2.数组中元素内容不同:前者为string类型的[文件名](包含后缀名),后者为Fi ...

随机推荐

  1. 编程语言 - 脚本编程 - JavaScript/Jquery/Ajax/XML/JSON/ActionScript3

    事件处理onmouseover <!DOCTYPE html> <html> <head> <meta charset="utf-8"&g ...

  2. NYOJ 654喜欢玩warcraft的ltl(01背包/常数级优化)

    传送门 Description ltl 非常喜欢玩warcraft,因为warcraft十分讲究团队整体实力,而他自己现在也为升级而不拖累团队而努力. 他现在有很多个地点来选择去刷怪升级,但是在每一个 ...

  3. Unable to load dynamic library 'zip.so' on Centos 6.8 useing php7.3

    背景: Centos6.8服务器升级php版本,从7.1升级到7.3,常用扩展都安装完成之后,报:Class 'ZipArchive' not found.一看就是zip扩展没有,需要手动安装了. 中 ...

  4. LeetCode #938. Range Sum of BST 二叉搜索树的范围和

    https://leetcode-cn.com/problems/range-sum-of-bst/ 二叉树中序遍历 二叉搜索树性质:一个节点大于所有其左子树的节点,小于其所有右子树的节点 /** * ...

  5. pthread_cond_timedwait

    该函数用于在同时等待条件变量时提供超时功能,不过该函数的超时时间是一个绝对时间.默认使用系统时间,这意味这,若修改系统时间,那么超时就不准确,有可能提前返回,也可能要几年才返回.这在某些需求下会导致b ...

  6. Checklist: 2019 05.01 ~ 06.30

    Golang Lessons learned porting 50k loc from Java to Go Five things that make Go fast Simple techniqu ...

  7. 记一次redis读取超时的排查过程(SADD惹的祸)

    问题背景 在业务使用redis过程中,出现了read timeout 的异常. 问题排查 直接原因 运维查询redis慢查询日志,发现在异常时间节点,有redis慢查询日志,执行sadd 命令花费了1 ...

  8. ESP8266物联网开发 一

    其实学了这么多,最终目的还是在于物联网. 好吧,我们就在这个的基础上来吧,先摸索,边学边摸索. 去网上买了8266开发板... 遇到的问题: USB线的问题.从同事那随便搞了一根USB线,然后写好程序 ...

  9. [转载]解决Android studio新建项目慢的问题

    原文地址为:https://blog.csdn.net/easion_zms/article/details/73181402 Android Studio 好处很多,但是当从github上或者导入其 ...

  10. maven多模块

    https://www.cnblogs.com/lichking2017/p/8996939.html