Вызывает ли следующий код неопределенное поведение?

Я хотел бы сделать что-то вроде этого

#include <iostream>
#include <memory>

struct Foo {};

using FooPtr = std::unique_ptr<Foo>;

FooPtr makeFoo() { return FooPtr(new Foo()); }

struct Baz
{
Baz(FooPtr foo) : Baz(std::move(foo), bar(foo)) {}
Baz(FooPtr foo, int something) : _foo{ std::move(foo) }, _something{ something } {}
private:
FooPtr _foo;
int _something;

static int bar(const FooPtr & ptr)
{
std::cout << "bar!" << std::endl;
return 42;
}
};

int main() {
Baz baz(makeFoo());
return 0;
}

Мой вопрос: порядок вычисления аргумента функции не определен, поэтому безопасно передавать значение, из которого будет перемещен один аргумент, и результат вызова другой функции с тот же экземпляр, передается как ссылка на const, как другой аргумент?

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

8

Решение

Фактическое «перемещение» не произойдет, пока конструктор перемещения std::unique_ptr<Foo> выполняется (все std::move() делает бросил const FooPtr & значение в FooPtr && Rvalue ссылка). Это не произойдет, пока два аргумента Baz вызывается конструктор, которому вы делегируете Чтобы это произошло, все аргументы этого конструктора должны быть оценены в первую очередь. Поэтому любое использование foo объект в оценке этих аргументов произойдет до фактического «движения» unique_ptr пример.

Поскольку вы передаете FooPtr (a.k.a std::unique_ptr<Foo> по значению и std::unique_ptr только для перемещения, это вызовет конструкцию перемещения при оценке первого аргумента в конструкторе с двумя аргументами. Поскольку порядок оценки аргументов не определен, это перемещение может произойти или не произойти до оценки второго аргумента. Поэтому поведение вашего примера является неопределенные.

9

Другие решения

std::move это не операция, это приведение к r-значению. Операция перемещения будет происходить внутри другого Baz конструктор. В результате то, что вы делаете, должно работать.

4

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

4
По вопросам рекламы [email protected]