对于变量其实对应的就是内存,而内存并没有表明一定是什么数据类型,所以判断变量是否是一个指针其实是一个参数类型匹配问题,在C++中支持函数的重载,那么不同的函数因为参数的不同从而匹配不同函数调用过程。
编译器在进行函数匹配调用的时候会遵循如下优先级:
重载函数 > 函数模板 > 可变参数。
#include <iostream>void Test(int a)
{std::cout<<"Normal Function"<<std::endl;
}template<typename T >
void Test(T a)
{std::cout<<"Template Function"<<std::endl;
}void Test(...)
{std::cout<<"... Function"<<std::endl;
}int main(int argc, char** argv)
{Test(100);Test(1, 100);Test(100.1);return 0;
}
有前面的语法基础以后,我们便可以利用可变参数与函数模板来进行相关程序设计进而判断一个变量是否为指针了。
#include <iostream>template<typename T >
bool isPtr(T * a)
{return true;
}bool isPtr(...)
{return false;
}class MyClass
{};int main(int argc, char** argv)
{int *ptr = nullptr;int var = 0;MyClass mc;if(isPtr(ptr)){std::cout<<"This is ptr"<<std::endl;}if(!isPtr(var)){std::cout<<"This is not ptr"<<std::endl;}if(!isPtr(mc)){std::cout<<"This is not ptr"<<std::endl;}return 0;
}
变参函数是C++从C中继承过来的,虽然这里传入类对象能正常编译运行,并得到正确结果。但这样做存在风险,编辑器在做代码静态检查时会报警告:warning: passing object of class type 'MyClass' through variadic function,因为类对象可能包含非POD(Plain Old Data)类型,这些类型不能通过变参函数来安全地复制和访问,触发对象的切割(slicing)问题,运行时可能发生意想不到的错误。
其实我们匹配到函数时已经可以区分了,能不能只进行匹配,不调用函数呢?当然可以,如下所示:
#include<iostream>
template<typename T >
char isPtr(T * a)
{return '\0';
}int isPtr(...)
{return 0;
}class MyClass
{};#define ISPTR(p) (sizeof(isPtr(p)) == sizeof(char))int main(int argc, char** argv)
{int *ptr = nullptr;int var = 0;MyClass mc;std::cout<<"ptr is ptr: "<< ISPTR(ptr)<<std::endl;std::cout<<"var is ptr: "<<ISPTR(var)<<std::endl;std::cout<<"mc is ptr: "<<ISPTR(mc)<<std::endl;return 0;
}
这里我们用了宏,编译时sizeof(isPtr(p))就能确定大小,这样就可以只匹配不调用函数。
首先可以明确的是,sizeof既是关键字也是运算符,它用来计算存放某一个量需要占用多少字节,它的结合性是从右到左。下图是来自C语言标准文档里的说明:
sizeof不是函数,虽然它的使用方法很像函数。如果sizeof是函数,那么 int i; sizeof i;这种表达式一定不能成立,因为函数参数不可能不用括号包裹起来。事实上这个sizeof i;可以正常编译运行的,这就说明sizeof绝对不是函数。因此sizeof它不会产生运行时开销,它的结果在编译时就已经确定,并且在程序运行的任何时刻都不会改变。
原文链接:https://blog.csdn.net/caoshangpa/article/details/140562652