Значение по умолчанию указателя функции в C++

каково значение по умолчанию указателя функции в C++? (Очевидно, этого не может быть!--1-->, Так что это?)

Как эта программа должна себя вести и почему?

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

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

5 ответов


в вашем случае объект 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

онлайн демо.


первый любой указатель может быть null. Это единственная универсальная истина о указателях. Тем не менее, ваш будет быть null, но не обязательно по причинам, которые вы, возможно, думаете;

C++11 § 8.5, p10

объект, инициализатором которого является пустой набор скобок, т. е. (), должно быть значение инициализации.

это важно, потому что ваша декларация включает это :

S s = S();

по определению инициализация значением:

C++11 § 8.5, p7

значение-инициализировать объект типа T означает:

  • Если T является (возможно в CV-квалифицированный) тип класса (п. 9), предоставленный пользователем конструктор (12.1), то конструктор по умолчанию для T называется (и инициализация плохо сформированной, если T имеет никакого доступного по умолчанию конструктор);

  • Если T является (возможно, CV-квалифицированным) типом класса non-union без предоставленного пользователем конструктора, то объект ноль-инициализировать и, если конструктор по умолчанию t неявно объявлен нетривиальным, этот конструктор вызывается.

  • Если T-тип массива, то каждый элемент инициализируется значением;

  • в противном случае, объект ноль-инициализировать.

что подводит нас к тому, что означает, что ваш тип объекта должен быть инициализирован нулем:

C++11 § 8.5, p5

to zero-инициализировать объект или ссылку типа T означает:

  • Если T-скалярный тип (3.9), то объекту присваивается значение 0 (ноль), взятое как интегральное постоянное выражение, преобразованное в T (103)

  • Если T является (возможно, CV-квалифицированным) типом класса non-union,каждый нестатический элемент данных и каждый субобъект базового класса инициализируется нулем и обивка инициализируется нулевым значением бита;

  • Если T является (возможно, CV-квалифицированным) типом объединения, Первый нестатический именованный элемент данных объекта инициализируется нулем, а заполнение инициализируется нулевыми битами;

  • Если T является массивом тип, каждый элемент инициализирован нулем;

  • Если T является ссылочным типом, то инициализация не выполняется.

103) как указано в 4.10, преобразование интегрального постоянного выражения, значение которого равно 0, в тип указателя приводит к нулевой указатель, то значение.

последнее является причиной того, что указатель равен null. Это будет не гарантируйте-так стандартом, который дали такой же код, но изменяющ заявление s для этого:

S s;

учитывая объявление, подобное приведенному выше, через стандарт берется другой путь:

C++11 § 8.5, p11

Если для объекта не указан инициализатор, то объектом является по умолчанию-инициализировать; если инициализация не выполняется, объект с автоматической или динамической длительностью хранения имеет неопределенное значение. [ Примечание: объекты со статической или потоковой длительностью хранения инициализируются нулем, см. 3.6.2.

какой тогда напрашивается последний вопрос, Что такое инициализация по умолчанию:

C++11 § 8.5, p6

по умолчанию-инициализировать объект типа T означает:

  • Если T является (возможно в CV-квалифицированный) тип класса (п. 9), конструктор по умолчанию для T называется (и инициализация плохо сформированной, если T имеет никакого доступного по умолчанию конструктор);

  • Если T-тип массива, то каждый элемент инициализируется по умолчанию;

  • в противном случае инициализация не выполняется.


указатель функции может быть NULL, и вы можете назначить ему NULL. Посмотрите здесь например:

#include <iostream>

using namespace std;

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

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

Я считаю, что вы называете конструктор структуры (с ()), f будет NULL.


указатель функции может быть нулевым, таким образом, вы можете указать, что они ни на что не указывают!


В C++ (и C) указатели (независимо от типа) не имеют значения по умолчанию per se; они берут то, что когда-нибудь случается в памяти в то время. Однако у них есть инициализированное значение по умолчанию NULL.

Инициализация По Умолчанию

когда вы явно не определяете конструктор, C++ вызовет инициализатор по умолчанию для каждой переменной-члена, который инициализирует указатели на 0. Однако, если вы определяете конструктор, но не устанавливаете значение для указателя не имеет значения по умолчанию. Поведение одинаково для целых чисел, поплавков и двойников.

в сторону

int main()
{
    S s = S();
    s.f();   // <-- This is calling `f`, not getting the pointer value.
}