类模板可以有非通用类型参数:
1.通常是整型(C++20标准可以用其它的类型);
2.实例化模板时必须用常量表达式;
3.模板中不能修改参数的值;
4.可以为非通用类型参数提供默认值。
优点:在栈上分配内存,易维护,执行速度快,合适小型数组。
缺点:在程序中,不同的非通用类型参数将导致编译器生成不同的类。
构造函数的方法更通用,因为数据的大小是类的成员(而不是硬编码),可以创建数组大小可变的类。
前言:
昨天我自己用模板类实现Array时,发现对于基本数据类型和类类型时,我自己实现的默认构造函数只能进行其中一个进行初始化,所以我就研究有没有即可以初始化基本数据类型,又可以初始化类类型,先说结论,代码如下:
template <class T, int len = 10>
class Array
{
private:
T items[len]; // 数组元素。
public:
//Array(){} //这样string类会初始化,但是基本类型如int不会初始化
//Array() { memset(items, 0, sizeof(items)); } //这样基本类型如int会初始化,但是string类不会调用默认构造函数,导致未定义行为造成乱码
Array() :items{} {} //初始化列表法
~Array() {} // 析构函数
T& operator[](int i) { return items[i]; } // 重载操作符[],可以修改数组中的元素。
const T& operator[](int i) const { return items[i]; } // 重载操作符[],不能修改数组中的元素。
};
或者:
template <class T, int len = 10>
class Array
{
private:
T items[len]; // 数组元素。
public:
//Array(){} //这样string类会初始化,但是基本类型如int不会初始化
//Array() { memset(items, 0, sizeof(items)); } //这样基本类型如int会初始化,但是string类不会调用默认构造函数,导致未定义行为造成乱码
Array() //采用小括号初始化则可以两者都初始化
{
for (int i = 0; i < len; ++i)
{
items[i] = T(); // 调用类型 T 的默认构造函数
}
} // 默认构造函数。
~Array() {} // 析构函数
T& operator[](int i) { return items[i]; } // 重载操作符[],可以修改数组中的元素。
const T& operator[](int i) const { return items[i]; } // 重载操作符[],不能修改数组中的元素。
};
对比不同的构造函数:
一、构造函数 Array() { memset(items, 0, sizeof(items)); }
对于 Array() { memset(items, 0, sizeof(items)); }这条构造函数,它是直接将内存中的值赋值为0,对于基本数据类型如:int,double等等这些可以进行初始化为0,但是当我们采用的是string类型的时候,会输出乱码,因为Array默认构造函数没有调用string的构造函数(本质是string类型会使用堆区内存,对于字符长的字符串会放在堆区,如果编译器有优化,会将字符短的字符串放在栈区),让其默认为空字符串,导致之后赋值会出现未定义行为。
测试代码如下:
#include <iostream> // 包含头文件。
using namespace std; // 指定缺省的命名空间。
template <class T, int len = 10>
class Array
{
private:
T items[len]; // 数组元素。
public:
Array() {