Какие коды должны знать ссылки на rvalue?

Я вижу, что у многих людей возникают проблемы с пониманием ссылок на rvalue. Будет ли "обычный" С++-код (например, который использует стандартную библиотеку, но не реализует его), должен знать о ссылках rvalue после выхода нового стандарта или могут ли люди/код просто притворяться, что ссылки rvalue не существуют? Ссылки rvalue в первую очередь касаются разработчиков библиотек или всех программистов?

Ответы

Ответ 1

Я ничего не видел, чтобы не согласиться с этой статьей в блоге GMan (aka gmannickg):

http://blackninjagames.com/?p=95

Сводка: любой, кто знает о copy-and-swap (и вообще правило три), должен знать о семантике перемещения (и, следовательно, ссылки на rvalue), потому что в результате меняются лучшие идиомы. Поэтому я думаю, что любой, кто вообще заботится о С++.

Я не думаю, что вам нужно знать, потому что, конечно, копирование и своп все еще работает, оно по-прежнему исключение и т.д. И я полагаю, кто-то может спорить о том, нужен ли "обычный" код и программисты на С++, чтобы узнать "копировать и сменять". Я надеюсь, что ответ "ну, ну, очевидно", но вы никогда не знаете.

Конечно, точка, с которой можно начинать использовать С++ 0x, будет варьироваться от места к месту. Вероятно, неплохо было бы отменить С++ 03 в ближайшее время.

Например, возврат огромных коллекций по значению в контекстах, которые недействительны для копирования, является лучшей ставкой, если вы можете положиться на назначение перемещения. Это не случай чего-то, что недействительно в С++ 03 становится действительным в С++ 0x, это код, который ужасно замедляется в С++ 03, который вы обойдете (даже если только с хорошо размещенным swap), становясь прекрасным в С++ 0x. Поэтому, если вы притворяетесь, что ссылки rvalue не существуют, вы будете продолжать работать над тем, что вам не нужно. Если вы сделаете прыжок, он может аккуратно вернуться к С++ 03, но запустить собаку медленно, что является болью.

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

Ответ 2

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

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

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

Они могут сделать это, сделав объекты этого класса подвижными, но не скопируемыми. Ярким примером этого будет поток - прямо сейчас вы не можете поместить какой-либо объект iostream в коллекцию, но в С++ 0x вы сможете.

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

Ответ 3

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

Помните, что С++ 0x будет совместим с 99,9% назад, поэтому весь существующий код все равно будет работать, что означает, что вы можете продолжать писать код С++ 0x, как если бы это был С++ 03.

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

Ответ 4

Возможно, вам не нужно знать о ссылках rvalue в смысле написания какой-либо функции, которая берет одну, но вы можете извлечь выгоду из понимания семантики перемещения, зная, что такое конструктор перемещения, и так далее. Если вы хотите использовать unique_ptr (и получить выгоду от перфоманса, поскольку у нее нет счетной ссылки), вам почти наверняка придется использовать std:: move (скажем, в коллекцию и из коллекции), и я не могу представить, чтобы это приближалось к тому, что в "что, если я положил a или или здесь?" что типичный студент второго курса справляется с указателями.

Я только что сделал "что нового в VС++ с участием С++ 0x" в Tech Ed Europe в Берлине, где был один слайд на ссылках на rvalue, и я в основном сказал: "Вам нужно знать, что они здесь, потому что они делают STL быстрее", но я еще не тренировал. Участники, которые, по-видимому, были лучше восприняты, чем варианты (более длинные), которые я имел в других беседах.

Ответ 5

Я согласен, что RValue References - это не всякая чашка чая - чашка довольно большая.

Из-за этого я рассказываю учащимся С++ 0x, что лучший подход к началу работы и использование RValue References - это использовать STL и охватывать его шаблоны проектирования со временем. Очень вероятно, что благодаря этому вы получаете выгоду от ссылок RValue, не понимая их полностью заранее.

Ответ 6

Скотт Майерс разделил функции С++ 0x на:

  • Возможности для всех.
  • Особенности для авторов классов.
  • Возможности авторов библиотеки.

RValues ​​- это, безусловно, авторы библиотек.

Ответ 7

В С++ 11 я бы передал все, что я планирую "хранить" или "потреблять" с помощью & &. Это приводит к наиболее эффективному коду, но "ломает" lvalue-совместимость и заставляет меня учитывать наличие двух (или более) версий каждого метода. К сожалению, вы получаете взрыв перестановок rvalue и const & поскольку количество аргументов увеличивается, и это делает получение указателей функций намного более "уродливым".

Вместо предоставления двух (или более) перегрузок, один для lvalues ​​и один для rvalue, я решил предоставить только перегрузку rvalue, и если пользователь хочет передать lvalue, они обертывают std:: ref(), std:: cref(), std:: move() или моя собственная вспомогательная копия(), которая делает копию явной и преобразует значение lvalue в значение r. (std:: ref() и std:: cref() могут работать, только если аргументы являются параметрами шаблона... в этом случае метод, вероятно, будет использовать std:: forward < > () для обработки автоматического обнаружения перемещения vs copy semantics.

template<typename T>
T copy( const T& v ) { return v; }

Если я пишу метод, который не "хранит" или "потребляет" вход, я использую const &

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

Другая практика, которую я рассматриваю, - это сделать только явные копии определенных классов.

class test  {
  public:
    test(){...};
    test( test&& t ){...}

  private:
    template<typename T>
    friend T copy(const T&t);

    test& operator=(const test&); // not implemented
    test( const test& t ){...}

    std::vector<char> large_data;
};

int main( int argc, char** argv ) {
  test x;
  test y = copy(x);
  test z = x; // error, test(const test&) is private...
  return 0;
}

Я бы использовал это для любого класса, который содержит любые "подвижные члены", такие строки, векторы, карты и т.д. Технически нет причин, по которым я не мог их скопировать, но почему бы мне не попробовать семантику перемещения везде, если я действительно хочу скопировать? С неявными копиями компилятор не может предупредить меня, что я делаю что-то потенциально дорогое.

Ответ 8

Если вы не внедряете класс семантики значения, вам действительно не нужно знать.

Изменить: или идеальная переадресация. Но это в основном использует библиотека.