Какие виды кода необходимо знать о ссылках rvalue? - PullRequest
14 голосов
/ 13 ноября 2010

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

Ответы [ 8 ]

6 голосов
/ 13 ноября 2010

В статье блога GMan (aka gmannickg) на эту тему я не видел ничего особенного:

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

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

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

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

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

Так что разумно было бы знать об этом, и во многих контекстах делают вид, что его не существует.

5 голосов
/ 13 ноября 2010

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

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

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

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

3 голосов
/ 13 ноября 2010

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

Я только что выступил с докладом «Что нового в VC ++ с C ++ 0x» на Tech Ed Europe в Берлине, в котором был один слайд по ссылкам на rvalue, и я в основном сказал: «Вы должны знать, что они здесь, потому что они делают STL намного быстрее ", но я не стал дальше тренироваться. Похоже, это было лучше воспринято участниками, чем (более длинные) варианты, которые у меня были в других выступлениях.

3 голосов
/ 13 ноября 2010

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

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

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

2 голосов
/ 14 ноября 2010

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

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

1 голос
/ 10 июня 2012

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

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

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;
}

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

1 голос
/ 14 ноября 2010

Скотт Мейерс разделил возможности C ++ 0x на:

  1. Особенности для всех.
  2. Особенности для авторов классов.
  3. Особенности для авторов библиотеки.

RValues ​​определенно авторы библиотеки.

0 голосов
/ 13 ноября 2010

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

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

...