Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is the `this` argument evaluated before or after other member function arguments?

In the following code a member function set() is called on a model, which is a null pointer. This would be undefined behavior. However, the parameter of the member function is a result of another function call that checks whether the model is a null pointer and throws in that case. Is it guaranteed that estimate() will always be called before the model is accessed or is it still Undefined Behaviour (UB)?

#include <iostream>
#include <memory>
#include <vector>


struct Model
{
    void set(int x)
    {
        v.resize(x);
    }

    std::vector<double> v;
};


int estimate(std::shared_ptr<Model> m)
{
    return m ? 3 : throw std::runtime_error("Model is not set");
}

int main()
{
    try
    {
        std::shared_ptr<Model> model; // null pointer here
        model->set(estimate(model));
    }
    catch (const std::runtime_error& e)
    {
        std::cout << e.what();
    }

    return 0;
}
like image 551
mentalmushroom Avatar asked Sep 02 '25 09:09

mentalmushroom


2 Answers

This is still undefined behavior (UB) as per expr.compound:

The postfix-expression is sequenced before each expression in the expression-list and any default argument. The initialization of a parameter, including every associated value computation and side effect, is indeterminately sequenced with respect to that of any other parameter.

(emphasis mine)

This means that the postfix expression model->set is sequenced before the expression estimate(model) in the expression-list. And since model is null pointer, the precondition of std::shared_ptr::operator-> is violated and hence this leads to UB.


like image 127
Anoop Rana Avatar answered Sep 05 '25 01:09

Anoop Rana


To my understanding this is undefined behavior at least from C++17:

  1. In a function-call expression, the expression that names the function is sequenced before every argument expression and every default argument.

As I interpret this, it actually guarantees that model->set is evaluated before any argument and thus invokes undefined behavior. It does not matter whether or not model is a raw pointer.

like image 27
nielsen Avatar answered Sep 04 '25 23:09

nielsen