Можно ли передать это в конструкторе в следующем примере? - PullRequest
3 голосов
/ 20 марта 2010
Class A
{
  A(B& b) : mb(b) 
   {
     // I will not access anything from B here
    }

  B& mb;
};


Class B
{
B(): a(*this)
{}

A a;
}

Иногда я сталкиваюсь с такой ситуацией, когда содержащийся объект должен использовать функциональность контейнеров. Ссылка на объект контейнера в содержащемся объекте, кажется, лучший способ сделать это. Конечно, я мог бы сделать это с указателем, таким образом, у меня мог бы быть сеттер setB(B* b) {mb = b;}, который я мог бы вызвать позже, когда я уверен, что B инициализирован, но я бы предпочел сделать это со ссылкой, что означает, что мне нужно инициализировать это в конструкторе, отсюда и проблема.

Ответы [ 3 ]

9 голосов
/ 20 марта 2010

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

Имейте в виду, что вы не можете безопасно вызывать какие-либо методы в B из конструктора A, поскольку B еще не завершил построение.

1 голос
/ 21 марта 2010

Соответствующая цитата из стандарта:

§3.8 [basic.life] / 6

Аналогично, до того, как началось время жизни объекта, но после того, как хранилище, которое будет занимать объект, было выделено, или, после того, как время жизни объекта закончилось, и до того, как хранилище, которое занимал объект, используется повторно или освобождено, любое значение который относится к исходному объекту, может быть использован, но только ограниченным образом. Такое lvalue относится к выделенному хранилищу (3.7.3.2), и использование свойств lvalue, которые не зависят от его значения, является четко определенным. Если преобразование lvalue в rvalue (4.1) применяется к такому lvalue, программа имеет неопределенное поведение; если исходный объект будет или имел тип класса не POD, программа имеет неопределенное поведение, если:

— the lvalue is used to access a non-static data member or call a non-static member function of the object, or 
— the lvalue is implicitly converted (4.10) to a reference to a base class type, or 
— the lvalue is used as the operand of a static_cast(5.2.9) (except when the conversion is ultimately to char& or unsigned char&), or 
— the lvalue is used as the operand of a dynamic_cast(5.2.7) or as the operand oftypeid.
1 голос
/ 20 марта 2010

Это зависит от того, что вы делаете в конструкторе А.

Объект B не полностью построен, пока конструктор не вернется. Кроме того, перед вводом тела конструктора B объекты внутри объекта B могут быть построены не полностью. Например:

class B
{
    A a;
    std::string str;

public:
    B() : a(*this)
    {
    }
};

В момент, когда вызывается A::A, str еще не создан. Если вы попытаетесь использовать str в A::A (прямо или косвенно), у вас будет неопределенное поведение.

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