提问者:小点点

this参数是在其他成员函数参数之前还是之后计算的?


在下面的代码中,在model上调用成员函数set(),它是一个空指针。这将是未定义的行为。但是,成员函数的参数是另一个函数调用的结果,该函数调用检查model是否为空指针并在这种情况下抛出。是否保证在访问model之前始终调用估计(),或者它仍然是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;
}

共3个答案

匿名用户

这仍然是未定义的行为(UB),根据expr.化合物:

后缀表达式表达式列表和任何默认参数中的每个表达式之前排序。参数的初始化,包括每个相关的值计算和副作用,相对于任何其他参数的初始化是不确定的。

(强调我的)

这意味着postfix表达式模型-

此外,expr. ref还可以用来查看这是UB:

后缀表达式后跟一个点。或箭头-

(强调我的)

这意味着评估箭头之前的后缀表达式model以及该评估的结果(即nullptr)与id-表达式操作符-

匿名用户

据我了解,这至少从C 17开始是未定义的行为:

当我解释这一点时,它实际上保证了模型-

匿名用户

[expr.call]/7:

postfix表达式在表达式列表中的每个表达式和任何默认参数之前排序。

在这种情况下,这意味着模型-

由于model是一个shared_ptr

前置条件:获取() ! = nullptr。

违反此先决条件会导致未定义的行为([structure.规范]/3.3)。