Наличие объекта Ref в качестве члена класса - PullRequest
0 голосов
/ 05 ноября 2018

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

class max_likelihood { 
public: 
MatrixXd dat
max_likelihood(const Ref<const MatrixXd>& dat_in)
{dat = dat_in;}

Я получаю работающий код, но в итоге создаю копию dat, чего я хотел бы избежать.

Я попытался сделать вместо:

class max_likelihood {
public:
const Ref<const MatrixXd>& dat;
max_likelihood(const Ref<const MatrixXd>& dat){}

Но это не работает и / или не позволяет мне получить доступ к ссылке на dat и даже не компилируется.

На основании моих исследований я нашел этот бит из этого вопроса

Если вы хотите переназначить Ref для ссылки на другой буфер, используйте новое размещение для повторного вызова конструктора Ref. Не забудьте сначала вызвать деструктора.

Я полагаю, что это может помочь ответить на мой вопрос, но я не знаю, что означают эти инструкции на практике, поэтому мой вопрос здесь. В частности, я предполагаю, что я создаю новый экземпляр объекта Ref для передачи переданной ссылки. Может ли кто-нибудь помочь мне интерпретировать ответ на этот вопрос или предложить более элегантный способ использования Ref объектов в классах, когда исходные данные создаются в другом месте, например, чтение из файла через main?

Любая помощь будет принята с благодарностью.

Ответы [ 4 ]

0 голосов
/ 05 ноября 2018

Вы можете установить и получить доступ к ссылке следующим образом:

class max_likelihood {
public:
   max_likelihood( const MatrixXd& input_dat): dat(input_dat) { }
   const MatrixXd& dat;
};

Но вы не можете изменить ссылку, то есть переназначить ее другому объекту для ссылки.

Если вам нужна эта функциональность, тогда вы должны изменить переменную-член на указатель, тогда вы можете легко изменить указатель. И если вы не хотите, чтобы пользователи вашего класса использовали указатель, вы можете добавить метод, который возвращает ссылку.

Если вы реализуете решение с указателем, имейте в виду, что исходный объект должен сохраняться до тех пор, пока anypody пытается получить к нему доступ, используя ваш класс max_likelihood. Возможно, вам следует использовать std::shared_ptr<> для предотвращения утечек памяти.

0 голосов
/ 05 ноября 2018

Переменная-член dat является константной ссылкой, которую необходимо инициализировать.

max_likelihood(const Ref<const MatrixXd>& argdat):dat(argdat){}

Вместо этого вы можете использовать неконстантную ссылку:

class max_likelihood {
public:
Ref<const MatrixXd> dat;
max_likelihood(const Ref<const MatrixXd>& dat):dat(argdat){}

По крайней мере, вы получите местный реф.

0 голосов
/ 05 ноября 2018

Я получаю работающий код, но в итоге создаю копию dat, чего я хотел бы избежать.

Использование ссылки во избежание копирования данных в этом случае - ужасная идея, поддержание ссылки в классе усложняет ситуацию. Поэтому, если MatrixXd правильно спроектирован для C ++ 11 или более поздней версии, просто используйте семантику перемещения:

class max_likelihood { 
public: 
   MatrixXd dat;
   max_likelihood(MatrixXd dat_in) : dat( std::move(dat_in) ) {}
   ...
};

если не выделить его динамически и передать право собственности:

class max_likelihood {  
public: 
   std::unique_ptr<MatrixXd> dat;
   max_likelihood(std::unique_ptr<MatrixXd> dat_in) : dat( std::move(dat_in) ) {}
   ...
};

Обычно наличие ссылки в классе не очень хорошая идея, во-первых, вы должны быть осторожны, чтобы не получить висячую ссылку, во-вторых, у вас будут сложности, если вы решите разрешить копирование и / или назначение вашего объекта.

0 голосов
/ 05 ноября 2018

Вы можете использовать список инициализатора:

struct max_likelihood { 
    MatrixXd& dat
    max_likelihood(MatrixXd& dat_in) : dat(dat_in) {}
};
...