我想做这样的事情
#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,作为另一个论点?
我认为问题可以归结为准确执行实际 move 操作的时间,这一点我还不清楚(特别是在打开优化功能时)。
最佳答案
在执行std::unique_ptr<Foo>
的move构造函数之前,不会发生实际的“move ”(所有std::move()
所做的工作都是将const FooPtr &
rvalue强制转换为FooPtr &&
rvalue引用)。在调用要委派的两个参数Baz
构造函数之前,不会发生这种情况。为了使这种情况发生,必须首先评估该构造函数的所有参数。因此,在评估这些参数时对foo
对象的任何使用都将发生在unique_ptr
实例的实际“move ”之前。
由于您要传递FooPtr
(也就是按值传递的std::unique_ptr<Foo>
,并且std::unique_ptr
是仅 move 的),因此在将两个参数的构造函数的第一个参数赋值时,将触发一个move构造。由于未指定参数的赋值顺序,因此该举或在第二个参数求值之前可能不会发生。因此,示例的行为未指定。
关于c++ - 以下代码是否会调用未定义的行为?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/27531495/