2013-08-09 4 views
8

У меня есть функция, которая возвращает вектор или набор:Как избежать копирования, когда я вернусь

set<int> foo() { 
    set<int> bar; 
    // create and massage bar 
    return bar; 
} 

set<int> afoo = foo(); 

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

ОК, обновите вопрос: если я собираюсь вернуть объект, определенный мной, не векторный или заданный объект, значит ли это, что я должен определить конструктор перемещения? следующим образом:

class value_to_return { 
    value_to_return (value_to_return && other) { 
    // how to write it here? I think std::move is supposed to be used? 
    } 
} 

ЧИТАЕТ!

+4

Теперь у вас нет копий на C++ 11. Он может делать ходы, но даже это почти наверняка будет оптимизировано [N/RVO] (http://en.wikipedia.org/wiki/Return_value_optimization). –

+11

«Как избежать копирования при возврате» - компиляция с компилятором выпущена не более 10 лет назад. –

+0

У меня очень соблазн свернуть все ответы, в которых не упоминаются ходы/rvalues. –

ответ

5

Оформить заявку return value optimization. Современный компилятор оптимизирует эту ситуацию, и в таких простых ситуациях копия не будет сделана ни на одном из основных компиляторов.

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

-3

Я обычно работаю вокруг этого, имея функцию сигнатуру

void foo(set<int> *x) 

Просто передайте его по ссылке или другой вариант уже упоминалось в комментарии.

Редактирование: я изменил тип аргумента, чтобы показать, что x можно изменить.

 set<int> s; 
     foo(&s); 

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

И лучше сделать это будет Либо использовать семантику перемещения с помощью C++ 11. Или верните контейнер и посмотрите в RVO в современных компиляторах.

+0

Я голосую за это, потому что это * единственный * ответ, который предлагает передать в выходной параметр. Идеальный ответ будет включать RVO и переместить конструкторы. –

+8

Почти соблазн проголосовать за _down_ за предложение выходных параметров. –

+0

@EdS: Выходные параметры ужасные. – Puppy

18

Модема C++ компилятор реализует: данный тип T:

  • Если T имеет доступную копию или переместить конструктор, компилятор может выбрать игнорировать копию. Это так называемый (названный) return value optimization (RVO), который был указан еще до C++ 11 и является , который поддерживается большинством компиляторов.
  • В противном случае, если T имеет номер move constructor, T перемещается (С C++ 11).
  • В противном случае, если T имеет конструктор копирования, T копируется.
  • В противном случае испускается ошибка времени компиляции.
+0

Пожалуйста, исправьте меня, если я ошибаюсь, но оптимизация возвращаемого значения AFAIK работает только тогда, когда вы строите объект непосредственно в операторе return следующим образом: 'return (set ) (...);' Интеллектуальный компилятор может преобразовать код в вопросе в эту форму, но для более сложных функций я бы предположил, что это не сработает. – cmaster

+0

@cmaster, в случае OP, RVO также применим. Прочитайте ссылку на wiki в своем ответе относительно RVO. :) – billz

+0

@cmaster: Оптимизация копии в случае возврата именованной переменной обычно называется NRVO, называемой оптимизацией возвращаемого значения и была реализована много лет назад большинством компиляторов. – JohannesD

Смежные вопросы