拷贝函数之类型萃取
来源:互联网 发布:苹果抹除数据后会怎样 编辑:程序博客网 时间:2024/06/08 12:58
经常在写模板顺序表的时候遇到一个问题,在拷贝元素的时候应该用for循环进行赋值,还是应用效率较高的memcpy.今天我们就来讨论一下。
首先看下它们各自的优缺点
(1) for 循环拷贝比较安全,容易想到并且实现;但是在顺序表元素太多时,时间复杂度高的情况下,for循环拷贝的效率比较低。
(2)memcpy是内存拷贝函数,任意内置类型的数据都可以拷贝,并且效率很高;但是memcpy的拷贝属于浅拷贝,在涉及字符串等自定义类型的数据时,拷贝会出现异常,程序会崩溃。
插入两个小概念:
1. POD:plain old data平凡类型(无关痛痒的类型)–基本类型
指在C++中与 C兼容的类型,可以按照 C的方式处理。
2. typeid可以获取到一个类型的名称,但是不能拿来做变量的声明。
下面介绍三种确定用for循环拷贝或者memcpy的方式。
第一种:封装一个判别是否是内置类型的函数IsPODtype(); bool IsPODtype(const char* type)
{
static char*arr[] = { "int", "char", "float", "double" };
int sz = sizeof(arr) / sizeof(arr[0]);
for (int i = 0; i < sz; i++)
{
if (strcmp(arr[i], type) == 0)
return true;
else
return false;
}
return false;
}
static char*arr[] = { "int", "char", "float", "double" }是将属于内置类型的四个数据类型进行罗列,将要拷贝的类型进行比对。
这种方式的调用函数为
template <class T>
void Copy(T*dest, T*src, int sz)
{
if (IsPODtype(typeid(T).name()))
{
memcpy(dest, src,sz*sizeof(T));//若为内置类型,可用memcpy拷贝,提高效率。
}
else
{
for (int i = 0; i < sz; i++)//若为自定义类型,不能用memcpy拷贝,深浅拷贝问题,用赋值
{
dest[i] = src[i];
}
}
}
这种方式容易理解并且想到。
第二种:将类型名称当作特殊的数据类型,将内置类型进行特化,这样,在创建实例时,模板类函数会对类型进行推演,从而找到对应的模板函数。
下面来看代码
struct truename
{
static bool IsPODtype()
{
return true;
}
};
struct falsename
{
static bool IsPODtype()
{
return false;
}
};
template
struct name
{
typedef falsename PODtype;
};
template < >
struct name
{
typedef truename PODtype;
};
template < >
struct name
{
typedef truename PODtype;
};
template < >
struct name
{
typedef truename PODtype;
};
template < >
struct name
{
typedef truename PODtype;
};
函数调用
template
void Copy(T*dest, T*src, int sz)
{
if (name::PODtype::IsPODtype())
{
memcpy(dest, src, sz*sizeof(T));//若为内置类型,可用memcpy拷贝,提高效率。
}
else
{
for (int i = 0; i < sz; i++)//若为自定义类型,不能用memcpy拷贝,深浅拷贝问题,用赋值
{
dest[i] = src[i];
}
}
}
这种方式对模板函数进行特化,也是不错的方式。
第三种:这种方式也是建立在模板函数的特化上,将使用for这里写代码片
循环还是memcpy拷贝进行函数封装,在主拷贝函数中调用次拷贝函数,三个函数构成函数重载
`
struct truename
{
};
struct falsename
{
};
template
struct name
{
typedef falsename PODtype;
};
template < >
struct name
{
typedef truename PODtype;
};
template < >
struct name
{
typedef truename PODtype;
};
template < >
struct name
{
typedef truename PODtype;
};
template < >
struct name
{
typedef truename PODtype;
};
template
void Copy(T* dest, T*src, int sz, truename)
{
memcpy(dest, src, sz*sizeof(T));
}
template
void Copy(T* dest, T*src, int sz, falsename)
{
for (int i = 0; i < sz; i++)
{
dest[i] = src[i];
}
}
template
void Copy(T*dest, T*src, int sz)
{
Copy(dest, src, sz, name::PODtype());
}
这种方式的实现也比较简单,关键是要理清思路。
`
看一下测试代码吧
int arr[4] = { 1, 2, 3, 4 }; int arr2[6] = { 0 }; int sz = sizeof(arr) / sizeof(arr[0]); Copy<int>(arr2, arr, sz); for (int i = 0; i < 6; i++) { cout << arr2[i] << endl; }
注:第二种和第三种方式都是类型萃取的方式,大家要细细品味和理解。
运行结果:
char* arr1[4] = { "11", "22", "33", "44" }; char* arr3[4] = { "00" }; int sz1 = sizeof(arr1) / sizeof(arr1[0]); Copy<char*>(arr3, arr1, sz1); for (int i = 0; i < 4; i++) { cout << arr3[i] << endl; }
运行结果
- 拷贝函数之类型萃取
- 深浅拷贝 & 类型萃取
- c++之类型萃取
- C++之类型萃取
- C++之类型萃取
- C++之类型萃取技巧
- 类型萃取
- 类型萃取
- 类型萃取
- 类型萃取
- 类型萃取
- 类型萃取
- 类型萃取
- 类型萃取
- 类型萃取
- 类型萃取
- 类型萃取
- C++ 模板 之 类型萃取 与 容器适配器
- Maven项目学习(二)配置打包和主函数
- VBA学习6_Excel VBA之暂停语句Stop、结束语句End、Exit详解
- ACL包过滤技术
- squbs概述
- lintcode房屋染色
- 拷贝函数之类型萃取
- Hadoop(1) : Linux下安装Java环境配置步骤详述
- java创建一个基本窗体
- springcloud框架下采用Grpc实现远程过程调用
- null和undefined的区别
- !=EOF的含义和原理
- 正则表达式
- 最小路径和
- Service启动流程源码分析(一):startService