Могу ли я создать в списке инициализатора члена ссылку на переменную-член, которой нет в списке? - PullRequest
0 голосов
/ 25 апреля 2018

Рассмотрим:

#include <string>
#include <iostream>

class Foo
{
     public:
         Foo( char const * msg ) : x( y ) 
         {
             y = msg;
         }

         std::string const & x;

     private:
         std::string y;
};

int main( int argc, char * argv[] )
{
    if ( argc >= 2 )
    {
        Foo f( argv[1] );
        std::cout << f.x << std::endl;
    }
}

Это компилирует и печатает первый параметр ... но я сомневаюсь, что он на самом деле "законный" / правильно сформированный.Я знаю, что список инициализатора должен инициализировать переменные в порядке их объявления в классе, чтобы вы не ссылались на переменные, которые еще не были инициализированы.Но как насчет переменных-членов , которых нет в списке инициализаторов ?Могу ли я безопасно создавать ссылки на них как на витрине?

(Пример, конечно, не имеет смысла. Просто для пояснения того, о чем я говорю.)

Ответы [ 3 ]

0 голосов
/ 25 апреля 2018

Вы можете сделать это 1 , потому что:

  1. x и y уже находятся в области действия ( [basic.scope.class] / 1 ).
  2. Поскольку вы получаете ссылку после того, как конструктор начал выполняться ( [class.cdtor] / 1 ), и хранилище для y уже получено ( [basic.life] / 7 ), эта ссылка может быть связана с y.

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


1 - Есть предостережение для языковых адвокатов. Технически ссылка должна быть привязана к действительному объекту ( [dcl.ref] / 5 ), то есть к объекту, чье время жизни началось. Однако, как и в случае с Core Language Issue 363 , ожидается, что он будет работать! Проблемная формулировка и возможное решение обсуждаются в Базовом языке, проблема 453 (любезно предоставлено @ T.C. В удаленном комментарии). В стандарте есть ошибка, но ваш код должен быть хорошо сформирован, и реализации обычно знают об этом.

0 голосов
/ 25 апреля 2018

А как насчет переменных-членов, которых нет в списке инициализаторов?

Вне зависимости от того, есть переменные в списке инициализаторов или нет, это не имеет значения. Если переменная отсутствует в списке инициализаторов (и не имеет инициализатора элементов по умолчанию), то она инициализируется по умолчанию.

y инициализируется после x. Это не из-за списка инициализатора элемента, потому что список инициализатора элемента не влияет на порядок инициализации элементов. Члены инициализируются в порядке их объявления.

Однако, y инициализирован или нет, также не имеет значения. Он хорошо сформирован для привязки ссылки к члену до его инициализации (за исключением привязки к виртуальной базе неинициализированного члена; в нем будет UB).


Что касается безопасности (или, возможно, правильности , точнее), я рекомендую вам уделить некоторое время, чтобы обдумать, что происходит при копировании Foo. На что будет ссылаться x? Это то, что пользователь класса ожидает?

0 голосов
/ 25 апреля 2018

Могу ли я безопасно создавать ссылки на них как на витрине?

Да, вы можете. Адрес хранения члена y известен независимо от того, инициализирован он или нет, поэтому x(y) справочная инициализация допустима.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...