Будет ли этот конструктор приемлемой практикой? - PullRequest
3 голосов
/ 30 апреля 2010

Давайте предположим, что у меня есть класс c ++, который правильно реализовал конструктор копирования и перегруженный оператор =. Под правильной реализацией я имею в виду, что они работают и выполняют глубокое копирование:

Class1::Class1(const Class1 &class1)
{
  // Perform copy
}
Class1& Class1::operator=(const Class1 *class1)
{
  // perform copy
  return *this;
}

Теперь допустим, что у меня есть и этот конструктор:

Class1::Class1(Class1 *class1)
{
   *this = *class1;
}

Мой вопрос: будет ли вышеуказанный конструктор приемлемой практикой? Это код, который я унаследовал и поддерживаю.

Ответы [ 4 ]

7 голосов
/ 30 апреля 2010

Я бы сказал «нет» по следующим причинам:

  • Традиционный конструктор копирования принимает свой аргумент как константную ссылку, а не как указатель.
  • Даже если вы примете указатель в качестве параметра, на самом деле должно быть const Class1*, чтобы показать, что аргумент не будет изменен.
  • Этот конструктор копирования неэффективен (или не будет работать!), Поскольку все члены Class1 инициализируются по умолчанию, а затем копируются с использованием operator=
  • operator= имеет ту же проблему; он должен принимать ссылку, а не указатель.

Традиционным способом «повторного использования» конструктора копирования в operator= является идиома копирования и замены . Я бы предложил реализовать класс таким образом.

2 голосов
/ 30 апреля 2010

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

2 голосов
/ 30 апреля 2010

Лично я не думаю, что это хорошая практика.

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

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

Аналогичным образом, для нестандартного оператора присваивания зачем разрешать присваивание из указателя при правильной разыменовке на сайте вызова? Это яснее и более идиоматично?

1 голос
/ 30 апреля 2010

Объекты и указатели на объекты - это две разные вещи. Как правило, когда вы передаете объекты вокруг, вы ожидаете, что они будут скопированы (хотя в идеале функции должны принимать константные ссылки, где это возможно, чтобы уменьшить / исключить ненужные копии). Когда вы передаете указатель, вы не ожидаете никакого копирования. Вы передаете указатель на определенный объект, и, в зависимости от кода, может иметь значение, что вы имеете дело с этим конкретным объектом, а не с его копией.

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

Я не могу придумать ни одной веской причины, по которой вы бы хотели сделать преобразование между указателем на тип и самим типом неявным или даже явным. Встроенный способ сделать это - разыменовать объект. Я полагаю, что может быть какой-то набор конкретных обстоятельств, о которых я не могу думать, где такие вещи могут быть необходимы, или хорошая идея, но я действительно сомневаюсь в этом. Конечно, я настоятельно рекомендую не делать этого, если у вас нет для этого особых и веских причин.

...