void指针,有一点点模板的味道

cskange 2014-08-18 01:09:38

模板功能强大,参数可以是任意C++合法类型。利用void指针,只能限于预定的几种类型。
例:写一个函数,用来交换两个 int 或者两个 float.





...全文
675 40 打赏 收藏 转发到动态 举报
写回复
用AI写文章
40 条回复
切换为时间正序
请发表友善的回复…
发表回复
cskange 2014-08-21
  • 打赏
  • 举报
回复
引用 39 楼 zhao4zhong1 的回复:
对学习编程者的忠告: 眼过千遍不如手过一遍! 书看千行不如手敲一行! 手敲千行不如单步一行! 单步源代码千行不如单步Debug版对应汇编一行! 单步Debug版对应汇编千行不如单步Release版对应汇编一行!
最后两档高大上
  • 打赏
  • 举报
回复
写错了 少于3个分支
  • 打赏
  • 举报
回复
引用 31 楼 cskange 的回复:
[quote=引用 3 楼 daiweifeng 的回复:] [quote=引用 楼主 cskange 的回复:] 模板功能强大,参数可以是任意C++合法类型。利用void指针,只能限于预定的几种类型。 例:写一个函数,用来交换两个 int 或者两个 float.
char类型用switch case[/quote] 用switch case是否比 if else 执行效率高些?[/quote] 我看资料上说上少于分支用switch case不会比if else快 按情况吧 效率什么的都差不多吧
赵4老师 2014-08-21
  • 打赏
  • 举报
回复
对学习编程者的忠告: 眼过千遍不如手过一遍! 书看千行不如手敲一行! 手敲千行不如单步一行! 单步源代码千行不如单步Debug版对应汇编一行! 单步Debug版对应汇编千行不如单步Release版对应汇编一行!
凡人_浪子 2014-08-20
  • 打赏
  • 举报
回复
个人观点,上述代码都存在不安全因素,千万不要用宏来实现swap

#include <iostream>

using namespace std;

#define MAX(a, b) ((a) > (b))? (a):(b)

void main()
{
	int a=5, c=5, b=0;
	MAX(++a, b);
	cout<<a<<endl;    //7
	MAX(++c, b+10);
	cout<<c<<endl;   //6
}
看吧,不可思议吧!看看boost中的swap吧!

namespace boost_swap_impl
{
  template<class T>
  void swap_impl(T& left, T& right)
  {
    using namespace std;//use std::swap if argument dependent lookup fails
    swap(left,right);
  }

  template<class T, std::size_t N>
  void swap_impl(T (& left)[N], T (& right)[N])
  {
    for (std::size_t i = 0; i < N; ++i)
    {
      ::boost_swap_impl::swap_impl(left[i], right[i]);
    }
  }
}

namespace boost
{
  template<class T1, class T2>
  void swap(T1& left, T2& right)
  {
    ::boost_swap_impl::swap_impl(left, right);
  }
}
超级能量泡泡 2014-08-20
  • 打赏
  • 举报
回复
引用 31 楼 cskange 的回复:
[quote=引用 3 楼 daiweifeng 的回复:] [quote=引用 楼主 cskange 的回复:] 模板功能强大,参数可以是任意C++合法类型。利用void指针,只能限于预定的几种类型。 例:写一个函数,用来交换两个 int 或者两个 float.
char类型用switch case[/quote] 用switch case是否比 if else 执行效率高些?[/quote] 当判断多的时候switch case 效率高。
winnuke 2014-08-20
  • 打赏
  • 举报
回复
引用 2 楼 zhao4zhong1 的回复:
仅供参考:
#include <stdio.h>
#define SWAP(a,b) do ((&(a))!=(&(b)))?((a)^=(b)^=(a)^=(b)):((a)=(a)); while (0)
char   *p1="1" ,*p2="2" ;
char    c1=1   , c2=2   ;
short   s1=1   , s2=2   ;
int     i1=1   , i2=2   ;
__int64 I1=1i64, I2=2i64;
float   f1=1.0f, f2=2.0f;
double  d1=1.0 , d2=2.0 ;
void main() {
    SWAP((int)p1,(int)p2);                printf("char *     %5s,   %5s\n",p1,p2);
    SWAP(c1,c2);                          printf("char       %5d,   %5d\n",c1,c2);
    SWAP(s1,s2);                          printf("short      %5d,   %5d\n",s1,s2);
    SWAP(i1,i2);                          printf("int        %5d,   %5d\n",i1,i2);
    SWAP(I1,I2);                          printf("__int64 %5I64d,%5I64d\n",I1,I2);
    SWAP(*(int     *)&f1,*(int     *)&f2);printf("float      %5g,   %5g\n",f1,f2);
    SWAP(*(__int64 *)&d1,*(__int64 *)&d2);printf("double    %5lg,  %5lg\n",d1,d2);

    SWAP(c1,c1);
    printf("%d\n",c1);
}
//char *         2,       1
//char           2,       1
//short          2,       1
//int            2,       1
//__int64     2,    1
//float          2,       1
//double        2,      1
//2
赵老师这个属于c风格的极致做法,没法比较对象,限制太多,无法充分发挥c++的威力。 void*这种依旧是运行期的,跟模板的编译器展开实现不一样的。
  • 打赏
  • 举报
回复
引用 5 楼 wangen12345 的回复:
[quote=引用 2 楼 zhao4zhong1 的回复:] 仅供参考:
#include <stdio.h>
#define SWAP(a,b) do ((&(a))!=(&(b)))?((a)^=(b)^=(a)^=(b)):((a)=(a)); while (0)
char   *p1="1" ,*p2="2" ;
char    c1=1   , c2=2   ;
short   s1=1   , s2=2   ;
int     i1=1   , i2=2   ;
__int64 I1=1i64, I2=2i64;
float   f1=1.0f, f2=2.0f;
double  d1=1.0 , d2=2.0 ;
void main() {
    SWAP((int)p1,(int)p2);                printf("char *     %5s,   %5s\n",p1,p2);
    SWAP(c1,c2);                          printf("char       %5d,   %5d\n",c1,c2);
    SWAP(s1,s2);                          printf("short      %5d,   %5d\n",s1,s2);
    SWAP(i1,i2);                          printf("int        %5d,   %5d\n",i1,i2);
    SWAP(I1,I2);                          printf("__int64 %5I64d,%5I64d\n",I1,I2);
    SWAP(*(int     *)&f1,*(int     *)&f2);printf("float      %5g,   %5g\n",f1,f2);
    SWAP(*(__int64 *)&d1,*(__int64 *)&d2);printf("double    %5lg,  %5lg\n",d1,d2);

    SWAP(c1,c1);
    printf("%d\n",c1);
}
//char *         2,       1
//char           2,       1
//short          2,       1
//int            2,       1
//__int64     2,    1
//float          2,       1
//double        2,      1
//2
赵老师的代码有错误啊,高手都直接就写在这了吗?该一下让我们都借鉴一下[/quote] 赵老师的代码都是可以运行的。。 下面绿色注释部分就是运行后的结果
jmppok 2014-08-19
  • 打赏
  • 举报
回复
Saleayas 2014-08-19
  • 打赏
  • 举报
回复
引用 17 楼 FENGQIYUNRAN 的回复:
[quote=引用 11 楼 cskange 的回复:] [quote=引用 9 楼 Saleayas 的回复:]
#define MAX_TYPE_SIZE 32
void swap(void *left, void *right, size_t size)
{
	unsigned char temp[MAX_TYPE_SIZE];
	memcpy_s(&temp, size, left, size);
	memcpy_s(left, size, right, size);
	memcpy_s(right, size, &temp, size);
}

#define TEST_SWAP(T, A, B, c) do { T a = A; T b = B; swap(&a, &b, sizeof (a)); TR(L"swap(%" L ###c L", %" L ###c L") = (%" L ###c L", %" L ###c L").", A, B, a, b); } while(0)


int _tmain(int argc, _TCHAR* argv[])
{
	TEST_SWAP(int, 1, 2, d);
	TEST_SWAP(double, 1.1, 2.2, f);
	TEST_SWAP(float, 1.2f, 2.3f, lf);
	TEST_SWAP(unsigned long long, 1L, 2L, ld);
	return 0;
}
这个函数的作用是指定两个地址和字节长度,交换两块内存的内容。蛮好的。 [/quote] 貌似,上一个TR函数没实现,速速奉上~[/quote] TR 是我自己的调试输出函数。 最早起这个名字,是因为和 VC 的 TRACE 宏冲突了。 我有一堆自己的 TR 调试宏,主要是用来调试输出的。 向我能使用的调试工具输出信息。 你可以理解为 wprintf 等等。 #define TR wprintf
zilaishuichina 2014-08-19
  • 打赏
  • 举报
回复
模板是编译时多态。 不管是void指针 还是 函数指针,都是运行时的多态。 这两个在本质上都是不一样的 模板更倾向于 宏定义, 在编译时就展开成对应的代码了。
WizardOz 2014-08-19
  • 打赏
  • 举报
回复
模板的好处是算法的实现和数据格式的实现分离。 而仅仅用void*指针类型是无法做到这一点的。 只有使用函数指针调用,在数据格式的实现阶段来绑定到具体的操作函数,才能实现类似于简单模板的功能。 可以参考一下C标准库中的qsort函数是如何对所有类型的数据排序的。
WizardOz 2014-08-19
  • 打赏
  • 举报
回复
你的exchange函数始终是需要写所有类型的交换代码在其中。 LZ应该试试函数指针

typedef int (*ExchangeFunc)(void*,void*);

int exchange_int(int* a,int* b)
{
      //...
      return 0;
}

ExchangeFunc func = exchange_int;


HaoYuan 2014-08-19
  • 打赏
  • 举报
回复
引用 16 楼 cskange 的回复:
[quote=引用 15 楼 Idle_ 的回复:] 模板的作用从源代码编译成二进制obj就结束了。 和程序执行时没关系。所以需要运行时动态确定类型的用不了模板。
这也可能是模板的定义和实现不能分别写到*.h和*.cpp的原因[/quote] 最新版本的C++貌似已经可以了
反转灵魂 2014-08-19
  • 打赏
  • 举报
回复
引用 30 楼 cskange 的回复:
[quote=引用 25 楼 reversesoul 的回复:] C++ 只有三个:封装,继承,多态。 整那么多形式上的东西干嘛,怎么用的顺怎么用,哪有什么相似不相似。要是真的找相似,基本类型和类类型我觉得也没什么区别。
当你有个小想法不知是否正确,最好编一段小程序来验证一下。如此日积月累,你就能茁壮成长了。 这里的小概念void*其实属于C,与C++无关 [/quote] 没区别吧,C++兼容所有C
cskange 2014-08-19
  • 打赏
  • 举报
回复
引用 18 楼 qq1134993111 的回复:
[quote=引用 16 楼 cskange 的回复:] [quote=引用 15 楼 Idle_ 的回复:] 模板的作用从源代码编译成二进制obj就结束了。 和程序执行时没关系。所以需要运行时动态确定类型的用不了模板。
这也可能是模板的定义和实现不能分别写到*.h和*.cpp的原因[/quote] 最新版本的C++貌似已经可以了[/quote] 是C++11吗?没找到下载
cskange 2014-08-19
  • 打赏
  • 举报
回复
引用 3 楼 daiweifeng 的回复:
[quote=引用 楼主 cskange 的回复:] 模板功能强大,参数可以是任意C++合法类型。利用void指针,只能限于预定的几种类型。 例:写一个函数,用来交换两个 int 或者两个 float.
char类型用switch case[/quote] 用switch case是否比 if else 执行效率高些?
cskange 2014-08-19
  • 打赏
  • 举报
回复
引用 25 楼 reversesoul 的回复:
C++ 只有三个:封装,继承,多态。 整那么多形式上的东西干嘛,怎么用的顺怎么用,哪有什么相似不相似。要是真的找相似,基本类型和类类型我觉得也没什么区别。
当你有个小想法不知是否正确,最好编一段小程序来验证一下。如此日积月累,你就能茁壮成长了。 这里的小概念void*其实属于C,与C++无关
赵4老师 2014-08-19
  • 打赏
  • 举报
回复
引用 24 楼 hjgzj 的回复:
[quote=引用 5 楼 wangen12345 的回复:] [quote=引用 2 楼 zhao4zhong1 的回复:] 仅供参考:
#include <stdio.h>
#define SWAP(a,b) do ((&(a))!=(&(b)))?((a)^=(b)^=(a)^=(b)):((a)=(a)); while (0)
char   *p1="1" ,*p2="2" ;
char    c1=1   , c2=2   ;
short   s1=1   , s2=2   ;
int     i1=1   , i2=2   ;
__int64 I1=1i64, I2=2i64;
float   f1=1.0f, f2=2.0f;
double  d1=1.0 , d2=2.0 ;
void main() {
    SWAP((int)p1,(int)p2);                printf("char *     %5s,   %5s\n",p1,p2);
    SWAP(c1,c2);                          printf("char       %5d,   %5d\n",c1,c2);
    SWAP(s1,s2);                          printf("short      %5d,   %5d\n",s1,s2);
    SWAP(i1,i2);                          printf("int        %5d,   %5d\n",i1,i2);
    SWAP(I1,I2);                          printf("__int64 %5I64d,%5I64d\n",I1,I2);
    SWAP(*(int     *)&f1,*(int     *)&f2);printf("float      %5g,   %5g\n",f1,f2);
    SWAP(*(__int64 *)&d1,*(__int64 *)&d2);printf("double    %5lg,  %5lg\n",d1,d2);

    SWAP(c1,c1);
    printf("%d\n",c1);
}
//char *         2,       1
//char           2,       1
//short          2,       1
//int            2,       1
//__int64     2,    1
//float          2,       1
//double        2,      1
//2
赵老师的代码有错误啊,高手都直接就写在这了吗?该一下让我们都借鉴一下[/quote] 赵老师的代码都是可以运行的。。 下面绿色注释部分就是运行后的结果[/quote] 在64位开发环境下可能需要修改。
cskange 2014-08-19
  • 打赏
  • 举报
回复
引用 21 楼 zilaishuichina 的回复:
模板是编译时多态。 不管是void指针 还是 函数指针,都是运行时的多态。 这两个在本质上都是不一样的 模板更倾向于 宏定义, 在编译时就展开成对应的代码了。
说得很明了
加载更多回复(20)

64,701

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧