Передайте объект RVO в std :: vector :: emplace_back - PullRequest
0 голосов
/ 31 октября 2019

Учитывая следующий массив:

std::vector<Foo> arr;
arr.emplace_back(calculate_foo());

emplace_back выигрывает от удаления временного объекта, так как его аргументы передаются на место в новом построенном элементе (поэтому здесь emplace_back будет запускать конструктор перемещения или копирования)Foo(foo)

Приведенный выше код создает, конечно, временный объект в calculate_foo, а затем копируется или перемещается в новый массив, в зависимости от конструкторов Foo.

Есть лиесть ли шанс сделать это быстрее и устранить временный объект?

1 Ответ

3 голосов
/ 31 октября 2019

Нельзя избежать создания временного аргумента для конструктора Foo с emplace_back. Если вы используете аргумент типа Foo, то это временный объект, который будет передан в конструктор размещенного объекта. В этом случае push_back будет в равной степени эффективен.

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

Пример:

struct ExpensiveMove {
    explicit ExpensiveMove(double d) {
         std::cout << "construct\n";
         std::fill(arr.begin(), arr.end(), d);
    }

    ExpensiveMove(const ExpensiveMove&) { std::cout << "expensive copy\n"; }
    ExpensiveMove(ExpensiveMove&&) { std::cout << "expensive move\n"; }
    ExpensiveMove& operator=(const ExpensiveMove&) { std::cout << "expensive copy ass\n"; return *this; }
    ExpensiveMove& operator=(ExpensiveMove&&) { std::cout << "expensive move ass\n"; return *this; }
    std::array<double, 1024> arr;
};

double calculate()
{
    return 4.2;
}

int main() {
    std::vector<ExpensiveMove> arr;
    arr.emplace_back(calculate());
}

В этом примере нет временных значений типа ExpensiveMove. Есть временный дубль, который не имеет значения.

...