ищет разъяснения по функции constexpr - PullRequest
1 голос
/ 13 октября 2019

Рассмотрим следующий сегмент кода:

#include <iostream>
using std::cout;
using std::endl;

class A
{
    public:
        //constexpr A (){i = 0;}
        constexpr A ():i(0){}
        void show (void){cout << i << endl; return;}
    private:
        int i;
};

class B
{
    public:
        constexpr B(A a){this->a = a;}
        //constexpr B(A a):a(a){}
        void show (void){a.show(); return;}
    private:
        A a;
};

int main (void)
{

    A a;
    B b(a);
    b.show();

    return (0);
}

Внутри определения class A, если текущее определение конструктора заменено закомментированным определением:

//constexpr A (){i = 0;}

следующееВозникает ошибка компиляции (обратите внимание, что номера строк соответствуют исходному коду):

g++ -ggdb -std=c++17 -Wall -Werror=pedantic -Wextra  -c code.cpp
code.cpp: In constructor ‘constexpr A::A()’:
code.cpp:8:30: error: member ‘A::i’ must be initialized by mem-initializer in ‘constexpr’ constructor
         constexpr A (){i = 0;}
                              ^
code.cpp:12:13: note: declared here
         int i;
             ^
make: *** [makefile:20: code.o] Error 1

Однако код прекрасно компилируется с любым определением для конструктора class B (текущее и определение, закомментированное ввоспроизводится исходный код.)

Я просмотрел следующие страницы с целью понимания происходящего здесь:

спецификатор constexpr (начиная с C ++ 11)

Постоянные выражения

Я должен признать, что не могу понять, почему список инициализатора элемента является обязательным в случае конструктора для A, а нев случае B.

цените ваши мысли.

1 Ответ

0 голосов
/ 13 октября 2019

A имеет конструктор по умолчанию (кстати, constexpr). Соответствующие требования для constexpr конструктора , который вы цитируете , следующие:

для конструктора класса или структуры, ... каждый не вариантныйСтатический член данных должен быть инициализирован.

Единственное требование, чтобы оно было «инициализировано». Не «явно инициализировано». Конструктор по умолчанию будет соответствовать требованию инициализации. A имеет конструктор по умолчанию. Таким образом, * a член класса B инициализируется его конструктором по умолчанию, что отвечает этому требованию, поэтому вам не нужно явно инициализировать его в списке инициализации конструктора B.

Onс другой стороны, у вашего сада int нет конструктора по умолчанию. По этой причине конструктор A constexpr должен инициализировать его явно.

...