Инициализация элемента данных экземпляра структуры в конструкторе?

#c #class #struct #initialization

#c #класс #структура #инициализация

Вопрос:

У меня есть класс c , который в качестве частного элемента данных имеет определенную структуру:

 Class example {

...

private:
   struct Impl;
   Implamp; structure_;
};
  

Предполагая, что структура Impl определена следующим образом:

 struct example::Impl{
    int m1;
    int m2;
    int m3;
};
  

как бы я мог инициализировать экземпляр struct ( structure_ ) в конструкторе класса?

Прямо сейчас у меня есть:

 example::example() :
     structure_ .m1(00),
     structure_ .m2(00),
     structure_ .m3(00) {
...
}
  

.. для списка инициализации, но я получаю эту ошибку:

‘example::structure_’ : должен быть инициализирован в списке базы конструктора / инициализатора элемента

как бы мне это исправить?

Спасибо

Ответ №1:

Impl — это ссылка, поэтому вам нужно инициализировать ее с помощью реального объекта Impl, прежде чем его можно будет использовать.

Ответ №2:

Если вы используете идиому pImpl, используйте указатель и выделите освободите его в классе, затем присвоите ему внутри ctor.

 Class example {

...

private:
   struct Impl;
   Impl* pimpl_
};

example::example() :
     pimpl_(new Impl())
{
  pimpl_->m1 = 00;
  pimpl_->m2 = 00;
  pimpl_->m3 = 00;
...
}

example::~example(){
  delete pimpl_;
}
  

Если вам действительно нужна ссылка, разыменуйте возвращаемый указатель из new и снова возьмите его адрес при его удалении:

 example::example() : impl_(*new Impl(), ...

example::~example(){ delete amp;impl_; }
  

Комментарии:

1. Это все еще недопустимый ctor-инициализатор .

2. В качестве примечания здесь: я обычно пытаюсь предложить реализовать pimpl-идиому с буфером правильного размера внутри структуры, которая скрывает реализацию. Таким образом, вам не придется выполнять дополнительную выборку l2-cache-miss / memory каждый раз, когда вы пытаетесь вызвать что-либо в экземпляре. 1 за хорошее общее описание pimpl-идиомы!

3. @Simon: Это становится проблематичным, так как иногда вы не можете быть уверены в выравнивании. Или откуда вы знаете размер?

4. Да, это действительно проблема. перечисление { IMPL_SIZE = 123; }; объединение { char implbuf[IMPL_SIZE]; двойное выравнивание dummy; } impl; .. которое выравнивает его с довольно строгим выравниванием в соответствии с двойным типом, который может быть изменен в соответствии с вашими потребностями. Убедитесь, что в конструкции есть assert или static assert, чтобы убедиться, что ваш sizeof (impl) равен или меньше IMPL_SIZE, чтобы избежать ошибок.

Ответ №3:

Поскольку ваша structure_ является ссылкой, на нее должно ссылаться что-то, созданное вне вашего класса «example». Вы могли бы либо преобразовать ссылку в указатель и каким-то образом выделить структуру, либо определить структуру в определении класса, что позволило бы вам создавать ее экземпляр напрямую, вместо использования ссылки.

Ответ №4:

Вы храните свою структуру по ссылке в своем классе. Ссылка должна указывать на физический объект, вы можете сделать две вещи. Сохраняйте объект по значению или по указателю.