为什么 std::unique_ptr<>.release() 在赋值 lhs 中的成员函数访问之前得到评估?

Why does std::unique_ptr<>.release() get evaluated before member function access which is in the lhs of assignment?

当访问 unique_ptr->get_id() 时,这会导致 segmentation fault,因为 release() 是预先 运行。

这里不保证顺序吗?

#include <iostream>
#include <memory>
#include <unordered_map>

class D
{
private:
        int id_;
public:
        D(int id) : id_{id} { std::cout << "D::D\n"; }
        ~D() { std::cout << "D::~D\n"; }

        int get_id() { return id_; }

        void bar() { std::cout << "D::bar\n"; }
};

int main() {
        std::unordered_map<int, D*> obj_map;
        auto uniq_ptr = std::make_unique<D>(123);

        obj_map[uniq_ptr->get_id()] = uniq_ptr.release();
        obj_map.at(123)->bar();

        return 0;
}

实际上可以保证这段代码永远会失败

根据cppreference

  1. In every simple assignment expression E1=E2 and every compound assignment expression E1@=E2, every value computation and side-effect of E2 is sequenced before every value computation and side effect of E1 (since C++17)

换句话说:在您的情况下,release() 保证在 get_id() 之前被调用。

这是因为 [expr.ass]/1 指出:

[...] In all cases, the assignment is sequenced after the value computation of the right and left operands, and before the value computation of the assignment expression. The right operand is sequenced before the left operand. With respect to an indeterminately-sequenced function call, the operation of a compound assignment is a single evaluation.

强调我的

根据上面的内容,首先评估右侧,然后评估左侧,然后进行赋值。应该注意的是,这仅在 C++17 之后得到保证。在 C++17 之前,左侧和右侧评估的顺序未指定。