6

C++中函数指针的默认值是多少?(显然不可能NULL,那是什么?)

这个程序应该如何表现,为什么?

struct S { void (*f)(); };

int main()
{
    S s = S();
    s.f();   // What is the value of s.f?
}
4

5 回答 5

18

首先,任何指针都可以为空。这是关于指针的一个普遍真理。也就是说,您的是空的,但不一定出于您可能认为的原因;

C++11 § 8.5,p10

初始值设定项为空括号集的对象,即(),应进行值初始化

这很重要,因为您的声明包括以下内容:

S s = S();

通过值初始化的定义:

C++11 § 8.5,p7

对 T 类型的对象进行值初始化意味着:

  • 如果 T 是具有用户提供的构造函数 (12.1) 的(可能是 cv 限定的)类类型(第 9 条),则调用 T 的默认构造函数(如果 T 没有可访问的默认构造函数,则初始化格式错误) ;

  • 如果 T 是没有用户提供的构造函数的(可能是 cv 限定的)非联合类类型,则该对象是零初始化的,并且如果 T 的隐式声明的默认构造函数是非平凡的,则调用该构造函数。

  • 如果 T 是一个数组类型,那么每个元素都是值初始化的;

  • 否则,对象被零初始化。

这给我们带来了零初始化的对象类型意味着什么:

C++11 § 8.5,p5

对 T 类型的对象或引用进行零初始化意味着:

  • 如果 T 是标量类型(3.9),则将对象设置为值 0(零),作为整数常量表达式,转换为 T (103)

  • 如果 T 是(可能是 cv 限定的)非联合类类型,则每个非静态数据成员和每个基类子对象都被初始化为零并且填充被初始化为零位;

  • 如果 T 是(可能是 cv 限定的)联合类型,则对象的第一个非静态命名数据成员被零初始化,填充被初始化为零位;

  • 如果 T 是数组类型,则每个元素都初始化为零;

  • 如果 T 是引用类型,则不执行初始化。

103) 如 4.10 所述,将值为 0 的整型常量表达式转换为指针类型会产生空指针值

后者是您的指针为空的原因。给定相同代码的标准将无法保证,但将声明更改为s

S s;

给定像上面这样的声明,通过标准采用不同的路径:

C++11 § 8.5,p11

如果没有为对象指定初始化器,则该对象是默认初始化的;如果不执行初始化,则具有自动或动态存储持续时间的对象具有不确定的值。[ 注意:具有静态或线程存储持续时间的对象是零初始化的,请参见 3.6.2。

然后引出了最后一个问题,什么是默认初始化

C++11 § 8.5,p6

默认初始化 T 类型的对象意味着:

  • 如果 T 是(可能是 cv 限定的)类类型(第 9 条),则调用 T 的默认构造函数(如果 T 没有可访问的默认构造函数,则初始化是错误的);

  • 如果 T 是数组类型,则每个元素都是默认初始化的;

  • 否则,不执行初始化。

于 2013-02-12T09:48:09.357 回答
8

在您的情况下,对象s是零初始化的,这意味着函数指针是NULL.

struct S { void (*f)(); };

int main()
{
    S s = S();
    if ( s.f == NULL)
       std::cout << "s.f is NULL" << std::endl;
}

输出:

s.f is NULL

在线演示

于 2013-02-12T09:26:18.013 回答
3

函数指针可以为NULL,这样你就可以表明它们不指向任何东西!

于 2013-02-12T09:25:53.587 回答
3

函数指针可以为 NULL,您可以将 NULL 分配给它。看看这里例如:

#include <iostream>

using namespace std;

struct S { void (*f)(); };

int main()
{
    S s = S();
    s.f = NULL;
    return 0;
}

我相信你调用结构的构造函数的方式(带()),f 将是 NULL。

于 2013-02-12T09:29:02.420 回答
0

在 C++(和 C)中,指针(无论类型如何)本身没有默认值;他们把当时发生在记忆中的东西拿走。但是,它们确实有一个默认的初始化值NULL

默认初始化

当您没有显式定义构造函数时,C++ 将调用每个成员变量的默认初始化程序,这将初始化指向0. 但是,如果您定义了构造函数,但不为指针设置值,则它没有默认值。整数、浮点数和双精度数的行为相同。

在旁边

int main()
{
    S s = S();
    s.f();   // <-- This is calling `f`, not getting the pointer value.
}
于 2013-02-12T09:24:43.467 回答