Копировать и перемещаться по иерархии наследования - PullRequest
3 голосов
/ 08 ноября 2019

Рассмотрим простую

class Foo
{
public:
   Foo(const std::string& name) : _name{name}

private:
   std::string _name;
};

, которую, как мы знаем, можно оптимизировать с помощью копии и переместить

class Foo
{
public:
   Foo(std::string name) : _name{std::move(name)}

private:
   std::string _name;
};

, но рассмотрим теперь иерархию:

class Base
{
protected:
   Base(const std::string& name) : _name{name}

private:
   std::string _name;
};

class Derived : public Base
{
public:
   Derived(const std::string& name) : A(name) {}
};

class Derived2 : public Derived
{
public:
   Derived2(const std::string& name) : Derived(name) {}
};

Чтоправильный способ реализации идиомы копирования и обмена здесь? Имеет ли смысл даже использовать копирование и обмен вместо передачи константной ссылки?

Редактировать: Пожалуйста, объясните отрицательные голоса.

1 Ответ

3 голосов
/ 08 ноября 2019

Передача по константной ссылке - все еще общепринятая мудрость

И, по всей вероятности, она будет продолжаться, см. Рекомендации по коду относительно этого.

Несмотря на то, что вы можете читать в блогах и т. Д., Вы должны придерживаться передачи константной ссылки для всех нормальных вариантов использования объектов, которые потенциально могут быть дорогостоящими для копирования - семантически вам не следуетне нужно беспокоиться о том, как тип X выполняет перемещение и копирование. Это все еще общепринятая мудрость, которая рекомендуется и дает необходимую гибкость для изменения реализаций на более поздней стадии . Если вы оставите код встроенным в заголовке, любой приличный компилятор сможет оптимизировать это в любом случае (или, возможно, с полной оптимизацией программы, если не в заголовке).

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

std::string особенно интересен из-за небольшая оптимизация строки - так что для многихмаленьких строк, которые в худшем случае могут привести к снижению производительности, близкому к коэффициенту 2. Почему? для небольших строк перемещение стоит так же дорого, как и копия, и ни перемещение, ни копирование не являются тривиальными, что означает отсутствие оптимизации при использовании идиомы копирования и перемещения.

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

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

Кроме того, не все типы дешевы в любом случае (например, std::array).

Если и только если , это было показано впрофилировщик, и вы все еще действительно очень обеспокоены этим - тогда вы, вероятно, захотите использовать прямую ссылку && вместо простой копии (если не решение - что-то третье)- затем позвоните std::forward для пересылки в базовые классы ( совершенная пересылка ).

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