我想做这样的事
#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;
}
我的问题是:函数参数求值的顺序是未指定的,因此传递一个将从一个参数中移出的值以及使用相同实例,作为对常量的引用传递,作为另一个参数传递?
我认为问题归结为实际 move 操作何时准确执行,这一点我并不完全清楚(尤其是在打开优化时)。
最佳答案
真正的“move ”直到std::unique_ptr<Foo>
的 move 构造函数才会发生。被执行(所有 std::move()
所做的就是将 const FooPtr &
右值转换为 FooPtr &&
右值引用)。这不会发生,直到两个参数 Baz
您委托(delegate)给的构造函数被调用。为了实现这一点,必须首先评估该构造函数的所有参数。因此,任何使用foo
评估这些参数的对象将在 unique_ptr
的实际“move ”之前发生实例。
由于您正在通过 FooPtr
(又名 std::unique_ptr<Foo>
按值,std::unique_ptr
是只 move 的,这将在评估双参数构造函数的第一个参数时触发 move 构造。由于参数的评估顺序未指定,该 move 可能会或可能在评估第二个参数之前不会发生。因此,您的示例的行为是未指定。
关于c++ - 以下代码是否调用未定义的行为?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27531495/