C++:使用定位new分配函数指针
有时候在设计库的的时候,你可能需要根据上下文参数,决定某个对象是要完全动态创建,或者是分配在一个已知的地方。典型的如,对大于一定字节数的对象采用动态new,否则使用定位new表达式;而分配函数指针是少见的用法。
int foo(int x, int y)
{
return x + y;
}
int main()
{
// 声明函数指针类型
using FunPtr = int(*)(int, int);
// 平常的函数指针初始化方法
FunPtr fptr1 = foo;
fptr1(1, 2);
// 注意类型void*
void *fptr2 = nullptr;
// 使用定位new初始化函数指针
new (&fptr2)FunPtr(foo);
((FunPtr)fptr2)(1, 2);
}
如果没有理解上面的实现,我们用简单的int型解释。
int *p1 = nullptr;
new (&p1)int(8); // p1指向内存地址编号为8的地方
int *p2 = (int*)8; // 上面p1定位new相当于p2的做法
重点为是p1、p2指向的地址是8,而非指向的内容是8。当然,至于内存地址8处的内容是什么,我们不关心。如果还是觉得有点晦涩,我们还可以简单一点:让指针指向一个可以有效验证的地方。
// 让定位new指向一个可以有效验证的地方,即变量a的地址。
int a = 8;
int *p3 = &a;
int *p4 = nullptr;
*(&p4) = &a; // 等同于p3的初始化操作
int *p5 = nullptr;
new (&p5)int((int)&a); // 将a的地址解释为一个整数,
// 最终由p5将这个整数解释为一个地址,即a的地址。
打印一下
cout << "p1: " << p1 << "\n"
<< "p2: " << p2 << endl
<< "p3: " << p3 << "\n"
<< "p4: " << p4 << "\n"
<< "p5: " << p5 << endl;
下面是一组输出
p1: 00000008
p2: 00000008
p3: 00D2F76C
p4: 00D2F76C
p5: 00D2F76C