1

It seems that for some reason when I try to call two functions on the same line, the first function receives an nullptr from ".get()" as the first argument

getSomePtr(someUniquePtr.get(), someArray)->moveUniquePtr(std::move(someUniquePtr));

But when separating these functions in to two separate lines, everything seems to work:

auto* somePtr = getSomePtr(someUniquePtr.get(), someArray);
somePtr->moveUniquePtr(std::move(someUniquePtr));

Why does this happen?

Matoy
  • 23
  • 3
  • Did you try with brackets enclosing getSomePtr(someUniquePtr.get(), someArray)? –  Nov 06 '21 at 19:50
  • 2
    Very similar to [this question](https://stackoverflow.com/questions/28336207/access-and-move-unique-ptr-in-a-function-call). Depending on your C++ version, it may be unspecified whether your pointer is moved first or accessed first. – Drew Dormann Nov 06 '21 at 19:53
  • What are the types involved? The function prototypes? The effect of `moveUniquePtr(std::move(someUniquePtr)` can be vastly different depending on the parameter type that function expects. – 1201ProgramAlarm Nov 06 '21 at 20:06
  • @DrewDormann I am unaware that the standard has changed regarding evaluation order of function arguments. AFAIK, all C++ versions allow them to be evaluated in any order prior to invocation. – Dúthomhas Nov 06 '21 at 20:08
  • 1
    @Dúthomhas • see the [undefined behavior](https://en.cppreference.com/w/cpp/language/eval_order) section, which mentions that the C++17 standard changed regarding the order of evaluation of function arguments. – Eljay Nov 06 '21 at 20:28
  • I've read that page many, many times. All C++17 adds is language specifically stating that the order of argument evaluation is unspecified. It didn’t actually change anything. – Dúthomhas Nov 06 '21 at 20:35
  • @Dúthomhas the changes are described, perhaps in clearer language, in [this answer](https://stackoverflow.com/a/15168020/16287) – Drew Dormann Nov 06 '21 at 20:56
  • 1
    OK, I, in my very tired state, was talking only about arguments to functions. You all are talking about the special case that is, not surprisingly, completely on-topic here... Sorry about that. Yes, C++17 clarifies that everything LHS of -> is sequenced before RHS. – Dúthomhas Nov 07 '21 at 00:10

1 Answers1

5

When evaluating an expression, function arguments are evaluated before the function that takes those arguments is called.

However, outside that rule, the compiler gets to choose the order of evaluation. It looks like, in your first case, it chose to evaluate moveUniquePtr before evaluating someUniquePointer.get(). Because one sub-expression modifies the state used in the other sub-expression, the result of the overall expression is not well-defined.

Splitting the expression into sequential statements, as in your second case, explicitly chooses the order of evaluation, and is the right thing to do in cases like this.

comingstorm
  • 25,557
  • 3
  • 43
  • 67