#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:
Вы храните свою структуру по ссылке в своем классе. Ссылка должна указывать на физический объект, вы можете сделать две вещи. Сохраняйте объект по значению или по указателю.