Правильное написание исходной функции на c ++ 11 - PullRequest
4 голосов
/ 23 ноября 2011

У меня болит голова: я читал так много блогов о семантике перемещения C ++ 11x, что мой мозг стал слабым, поэтому, пожалуйста, кто-нибудь может дать мне краткое, но приятное руководство о том, как заставить следующий код работать эффективно? Учитывая класс Foo, я хочу иметь возможность писать функции, которые возвращают Foo объекты в разных состояниях (иногда называемые функциями-источниками), и делать это максимально эффективно.

class Foo {
    // Some methods and members
};

Foo getFirstFoo() {
    Foo foo;
    // Do some things to foo
    return foo;
} 

Foo getSecondFoo() {
    Foo foo;
    // Do some different things to foo
    return foo;
} 

int main() {
    Foo f = getFoo();
    // use f ...
    f = getSecondFoo();
    // use f ...
    return 0;
}

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

В C ++ 03 мои варианты заключаются в том, чтобы обернуть возвращаемый объект в auto_ptr (большой недостаток заключается в том, что код получателя должен знать, чтобы обрабатывать умный указатель), или скрестить пальцы и надеяться, что некоторые может иметь место оптимизация (вероятно, для первой строки в main, для второй - меньше). C ++ 11x, кажется, обеспечивает что-то лучшее благодаря семантике перемещения, но как бы мне воспользоваться этим? Поэтому мне нужно изменить способ возврата объектов в исходных функциях или добавить какой-либо конструктор перемещения в Foo, или в оба?

1 Ответ

6 голосов
/ 23 ноября 2011

Это уже оптимально 1 при условии, что сгенерированы конструкторы перемещения 2 :

class Foo {
    public: 
        Foo(Foo&&) = default;
        Foo& operator=(Foo&&) = default;
};

По умолчанию возвращаемые значения являются ссылками rvalue.


1 Ну ... при условии, что ваш класс Foo вообще выигрывает от постройки ходов.Помните, что move - это оптимизация copy .Некоторые копии не могут быть улучшены!Например, не подходит:

struct Foo  { int data; };
struct Foo2 { int data[5<<10]; };

хорошо подходит:

struct Foo3 { std::vector<std::string> data; };

См. Перемещение семантики - что это такое? для более общего понимания подобных вещей.


2 Не все компиляторы пока поддерживают это (даже если они делают реализуют ссылки на значения ), поэтому вам, возможно, придетсянапишите

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