прохождение тяжелых предметов C ++ 0x - PullRequest
7 голосов
/ 18 июня 2011

У меня есть функция, которая производит тип дорогого объекта (содержащий векторы и карты не фиксированного размера), поэтому я действительно хочу избежать вызова копий c'ors.

До сих пор я только что вернулсяstd :: shared_ptr из метода и использовал его, но я думаю, что это ужасно и требует, чтобы определение типов было действительно полезным.

Я знаю две вещи, которые могут мне помочь.Во-первых, скопируйте elision, а во-вторых, это семантика перемещения.

Моя проблема в том, что я знаю, как правильно использовать ни то, ни другое.Мое исследование показало, что копирование полностью выполняется компилятором и не зависит от st'd.На самом деле я не хочу полагаться только на это.

Так как мне убедиться, что задание перемещения вызывается и имеет ли оно то, что мешает компилятору делать копию elision.

ResultSet &&generateResults()
{
    //ResultSet a(); :S
    ResultSet a;
    a.populat(...
    //blah blah blah
    return a;
}

//else where (where the && assignment operator is overloaded
ResultsSet b = generateResults();

В этом случае это самый правильный способ закодировать это?и если нет, как я мог бы улучшить это.Я счастлив использовать C ++ 0x только конструкции.

Кстати: мой компилятор gcc 4.6

Ответы [ 5 ]

4 голосов
/ 19 июня 2011

В этом случае это самый правильный способ закодировать это?

На самом деле это «наименее правильный» способ: вы возвращаете ссылку на автоматический объект. Когда функция возвращается, клиент получает ссылку на объект, который больше не существует.

В этом отношении нет разницы между ссылками lvalue и ссылками rvalue. Так что просто избавьтесь от ссылки на rvalue и верните результат по значению. Вы либо получите NRVO, либо переместитесь в семантику.

4 голосов
/ 18 июня 2011

Хороший ответ на ваши вопросы можно найти в этой серии постов в блоге Дэйва Абрахамса:

http://cpp -next.com / Архив / 2009/08 / хотите-скорость-передача по значению /

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

Короче говоря, копия elision имеет приоритет. Если по какой-либо причине это не происходит (или не может произойти), компилятор должен сначала рассмотреть конструктор перемещения и, наконец, конструктор копирования.

3 голосов
/ 18 июня 2011

Ваше исследование неверно.Копия elision абсолютно стандартна.Это не обязательно, но официально разрешено.В примере с вашей функцией я бы определенно ожидал, что она будет применена, поскольку преобразование относительно тривиально.

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

О, и вам нужно перегрузить конструктор перемещения, не оператор присваивания перемещения, для этого конкретного фрагмента кода, хотя, конечно, в идеале вы должны делать и то и другое.

ResultSet a();

Не определяет никакую переменную, но объявляет функцию с именем a, которая ничего не берет и возвращает ResultSet.

3 голосов
/ 18 июня 2011

Если вы не любите читать, вот ссылка на видео о rvalues ​​и семантике перемещения: http://channel9.msdn.com/Shows/Going+Deep/C9-Lectures-Stephan-T-Lavavej-Standard-Template-Library-STL-9-of-n

0 голосов
/ 18 июня 2011

Вы можете узнать о конструкторах перемещения , и я уверен, что кто-то предоставит вам пример.

Но другой вариант, который вы могли бы рассмотреть, - unique_ptr,Для вашего приложения оно должно работать так же хорошо, как shared_ptr, и оно будет значительно более эффективным.(Тем не менее, вы, возможно, захотите эти typedefs.)

...