是否定义了函数参数中的内部执行顺序?

时间:2017-02-20 15:38:25

标签: c++ c++11 dynamic-memory-allocation operator-precedence

我们假设我们有以下代码片段:

void foo(std::unique_ptr<Data> p1, std::unique_ptr<Data> p2){
    bar(p1);
    bar(p2);
}

int main(){
    foo( std::unique_ptr<Data>{new Data}, std::unique_ptr<Data>{new Data});
}

问题是:运行此代码后是否会释放内存(无论发生什么情况)?

标准说我们不能依赖语句的顺序是函数参数,但是内部函数调用/内存分配等呢?这在这里是否很重要?

1 个答案:

答案 0 :(得分:7)

  运行此代码后,

将永远释放内存(无论发生什么情况)?

在C ++之前17 :没有。一个可能的执行顺序是:

  1. new Data
  2. new Data
  3. unique_ptr构造函数
  4. unique_ptr构造函数
  5. 如果(1)抛出,我们没事。如果(2)抛出,我们还没有实际运行unique_ptr构造函数,所以我们没有任何清理机制来从(1)中释放内存。那会泄漏。只有在(1)和(2)抛出都没有的情况下,我们才会好。

    这就是标准引入std::make_unique

    的原因
    foo( std::make_unique<Data>(), std::make_unique<Data>() );
    

    没有这个问题 - new现在内部分组到unique_ptr构造函数。因此,如果一个人成功,那么它已经被包裹在其RAII后卫中。

    C ++ 17之后:是的。虽然函数参数的评估顺序仍未指定,但是有一个新规则,即此类评估不能交错。也就是说,给定f(g(a), h(b)),潜在的评估顺序为:[f, g, a, h, b][f, h, b, g, a]。我们无法再在ab之前评估gh,这是原始代码的潜在问题。