Создание класса с помощью ссылок на объекты - PullRequest
1 голос
/ 25 ноября 2011

Я пытаюсь понять конструктор, используемый в классе, реализованном в библиотеке, которую я использую.Ключевые компоненты класса SequenceAnalyzer выглядят так:

class SequenceAnalyzer {
  protected:
    std::vector<cv::Mat> images_;

  public:
    SequenceAnalyzer( std::vector<cv::Mat> *images = NULL )
    {
        if (images != NULL)
          images_ = (*images);
    }

};

При создании экземпляра этого класса в моем main я передаю ему ссылку на вектор:

std::vector<cv::Mat> myImages;
SequenceAnalyzer se(&myImages);

Теперь переходим вмои изображения по ссылке передали классу свое местоположение в памяти.Но мое понимание оператора (* images) означает, что их адрес был разыменован, и поэтому оператор = затем копирует содержимое.

Есть ли какое-либо преимущество в передаче myImages в класс таким образом?Почему указатели используются в первую очередь, если они все равно не заканчиваются на сохраненных копиях?

Ответы [ 4 ]

1 голос
/ 25 ноября 2011

При создании экземпляра этого класса в моем основном я передаю ему ссылку на вектор:

std::vector<cv::Mat> myImages;
SequenceAnalyzer se(&myImages);

Нет, вы не делаете.

& для типа указывает на ссылочный тип;& в выражении является оператором address-of и возвращает указатель!Вот почему ваш конструктор принимает указатель, иначе это не сработает.

Теперь передача моих изображений по ссылке [указатель] передает их местоположение в памятик классу.Но мое понимание оператора (*images) означает, что их адрес был разыменован, и поэтому оператор = затем копирует содержимое.

Исправить.

Есть ликакое-либо преимущество в передаче myImages в класс таким образом?Почему указатели используются в первую очередь, если они в любом случае не заканчиваются сохраненным копированием?

Предположительно, программист хотел избежать копирования вектора дважды (один раз дляаргумент и снова для хранения в качестве члена).Это необычно делать с помощью указателя, а не ссылки.


Я бы вместо этого написал:

class SequenceAnalyzer {
  protected:
    std::vector<cv::Mat> images_;

  public:
    SequenceAnalyzer(const std::vector<cv::Mat>& images = std::vector<cv::Mat>())
       : images_(images) {};
};

Теперь у вас есть параметр ссылки, значение по умолчанию итакже вы правильно инициализируете.

1 голос
/ 25 ноября 2011

Нет никаких преимуществ.Я написал бы такой же код как:

SequenceAnalyzer( const std::vector<cv::Mat>& images = std::vector<cv::Mat>()) :
    images_(images)
{
}

Теперь мне не нужно беспокоиться об указателях:

std::vector<cv::Mat> myImages;
SequenceAnalyzer se(myImages);
0 голосов
/ 25 ноября 2011

Может быть полезно знать, что даже если вы скопируете вектор, вы скопируете только заголовки изображения (структура, содержащая тип, ширину, высоту и т. Д.).Объекты Mat инкапсулируют умный указатель на данные, поэтому глубокая копия данных изображения происходит только при вызове определенных функций (Mat :: copyTo (), Mat :: clone ())

0 голосов
/ 25 ноября 2011

Передача параметра указателем (или ссылкой) вместо значения избегает временного копирования.Таким образом, копирование выполняется только при необходимости, а не при передаче его в качестве параметра.Еще одним преимуществом является то, что вы можете иметь значение по умолчанию NULL, не создавая конструктор по умолчанию.В этом случае неявный конструктор по умолчанию должен делать то же самое.

Более элегантный способ может быть следующим:

SequenceAnalyzer(const std::vector<cv::Mat>& images) {
  images_ = images;
}

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

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