c++ - 以下代码是否调用未定义的行为?

标签 c++ c++11 move rvalue sequence-points

我想做这样的事

#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/

相关文章:

c++ - 生成 boost::hana::set 的常量表达式问题

c++ - 如何在 C++ 中仅读取文本文件中的数字

c++ - std::function 的移动构造函数的异常规范是什么?

c++ - 如何通过引用为 C++0x 传递 Lambda 表达式参数

c++ - 复制包含原子成员的对象的地址?

CSS move 和平移属性不能使用关键帧同时工作

C++:通过类成员方法访问类成员

c# - move/调整另一个窗口的大小并重新绘制它?

C++ std move 文件错误?

c++ - boost::variant 和 STL 容器 - 我做错了吗?