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

4nkexdtk  于 2023-05-20  发布在  其他
关注(0)|答案(3)|浏览(163)

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

ubbxdtey1#

根据表达式化合物,这仍是未定义行为(UB):
postfix-expressionexpression-list和任何默认参数中的每个expression之前排序。参数的初始化,包括每个相关的值计算和副作用,相对于任何其他参数的初始化顺序不确定。
(强调我的)
这意味着后缀表达式model->set在表达式列表中排序在表达式estimate(model)之前。由于model是空指针,std::shared_ptr::operator->的前提条件
被违反
,因此这导致UB。

a1o7rhls

a1o7rhls2#

根据我的理解,这是未定义的行为at least from C++17
1.在函数调用表达式中,命名函数的表达式在每个参数表达式和每个默认参数之前排序。
正如我所解释的,它实际上保证了model->set在任何参数之前被求值,因此调用了未定义的行为。model是否是原始指针并不重要。

bvjveswy

bvjveswy3#

[expr.call]/7:

  • postfix-expression* 在 expression-list 中的每个 expression 和任何默认参数之前排序。

在这种情况下,这意味着model->setestimate(model)之前被评估。
由于model是一个shared_ptr<Model>model->set使用shared_ptr的重载operator->,它有以下前提条件([util.smartptr.shared.obs]/5):

  • 前置条件:* get() != nullptr

违反这个前提条件会导致未定义的行为([structure.specifications]/3.3)。

相关问题