This results in a SEGFAULT when accessing unique_ptr->get_id() as release() is run beforehand.
Is the ordering not guaranteed here?
#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;
}
CodePudding user response:
It's actually guaranteed that this code will always fail.
According to cppreference:
- 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)
In other words: release()
is guaranteed to be called before get_id()
in your case.
CodePudding user response:
This is because of [expr.ass]/1 which states:
[...] 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.
emphasis mine
According to the above the right hand side gets evaluated first, then the left hand side, then the assignment happens. It should be noted that this is only guaranteed since C 17. Before C 17 the order of the left and right sides evaluations was unspecified.