Стоит ли добавлять сеттер с поддержкой перемещения -?

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

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

class Bar {
public:
    Bar() : _array(1000) {}
    Bar(Bar const & other) : _array(other._array) {}
    Bar(Bar && other) : _array(std::move(other._array)) {}
    Bar & operator=(Bar const & other) {
        _array = other._array;
        return *this;
    }
    Bar & operator=(Bar && other) {
        _array = std::move(other._array);
        return *this;
    }
private:
    vector<string> _array;
};

class Foo {
public:
    void SetBarByCopy(Bar value) {
        _bar = value;
    }
    void SetBarByMovedCopy(Bar value) {
        _bar = std::move(value);
    }
    void SetBarByConstRef(Bar const & value) {
        _bar = value;
    }
    void SetBarByMove(Bar && value) {
        _bar = std::move(value);
    }
private:
    Bar _bar;
};

Вообще говоря, в прошлом я использовал const -ref для функций установки для не встроенных -типов. Варианты, которые я рассматривал, заключались в том, чтобы пройти по значению -, а затем перейти(SetByMovedCopy), передайте const -ref, затем скопируйте(SetByConstRef)и, наконец, принять значение r --ref, затем переместить(SetByMove). В качестве основы я также включил передачу -по значению -, а затем копирование (SetByCopy).. ПСВ,компилятор жаловался на двусмысленность при включении перегрузок pass -by -value и r -value -ref.

В экспериментах с компилятором VS2010 я обнаружил вот что:

Foo foo;
Bar bar_one;

foo.SetByCopy(bar_one);
// Bar::copy ctor called (to construct "value" from bar_one)
// Foo::SetByCopy entered
// Bar::copy operator= called (to copy "value" to _bar)
// Foo::SetByCopy exiting
// Bar::dtor called (on "value")

valueявляется копией -, созданной из bar_one, тогда valueкопируется в bar. valueуничтожается и берет на себя все затраты на уничтожение всего объекта. Выполняются 2 операции копирования.

foo.SetByMovedCopy(bar_one);
// Bar::copy ctor called (to construct "value" from bar_one)
// Foo::SetByCopy entered
// Bar::move operator= called (to move "value" into _bar)
// Foo::SetByCopy exiting
// Bar::dtor called (to destruct the moved "value")

valueэто копия -, построенная из bar_one, затем valueперемещается в _bar, затем выпотрошенный valueуничтожается после выхода из функции, предположительно с меньшими затратами. 1 копирование и 1 перемещение.

foo.SetByConstRef(bar_one);
// Foo::SetByConstRef entered
// Bar::copy operator= called (to copy bar_one into _bar)
// Foo::SetByConstRef exiting

bar_oneкопируется непосредственно в _bar. 1 операция копирования.

foo.SetByMove(std::move(bar_one))
// Foo::SetByMove entered
// Bar::move operator= called (to move "value" into _bar)
// Foo::SetByMove exited

bar_oneперемещается непосредственно в _bar. 1 операция перемещения.


Таким образом, версии const -ref и move в данном случае наиболее эффективны. Теперь, ближе к делу, то, что я хочу сделать, это что-то вроде этого:

void SetBar(Bar const & value) { _bar = value; }
void SetBar(Bar && value) { _bar = std::move(value); }

Я обнаружил, что здесь происходит следующее: если вы вызываете Foo::SetBar, компилятор выбирает функцию в зависимости от того, передаете ли вы значение l -или значение r -. Вы можете форсировать проблему, позвонив std::moveкак таковой:

foo.SetBar(bar_one); // Const-ref version called
foo.SetBar(Bar()); // Move version called
foo.SetBar(std::move(bar_one)); // Move version called

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

7
задан Mike E 21 May 2012 в 22:13
поделиться