gpt4 book ai didi

c++ - 使用后递增索引的数组分配中的异常安全

转载 作者:太空狗 更新时间:2023-10-29 21:19:23 26 4
gpt4 key购买 nike

在这段代码中:

template<class T>
void Stack<T>::Push( const T& t )
{
if( vused_ == vsize_ ) // grow if necessary
{
size_t vsize_new = vsize_*2+1; // by some grow factor
T* v_new = NewCopy( v_, vsize_, vsize_new );
delete[] v_; // this can't throw
v_ = v_new; // take ownership
vsize_ = vsize_new;
}
v_[vused_] = t;
vused++;
}

我们努力做到异常安全和异常中立。它是通过 NewCopy() 辅助函数(复制指向的内存并返回指向复制值的指针)来实现的,它遵循这些原则(我们在这里对该函数不感兴趣,它是异常安全和中立)。最后,一切正常,因为

  v_[vused_] = t;
vused++;

如果赋值没有抛出,我们只会改变 Stack 的状态。如果我们写

  v_[vused_++] = t;

会不会违反异常安全?我的猜测是肯定的(后增量运算符返回旧值但它确实增量变量返回之前,然后在它返回之后执行赋值,所以在异常的情况下对象状态是无效的)。但我可能错了(?)

最佳答案

根据标准,1.9/15:

When calling a function (whether or not the function is inline), every value computation and side effect associated with any argument expression, or with the postfix expression designating the called function, is sequenced before execution of every expression or statement in the body of the called function.

所以当我们调用时:

v_[vused_++]

也就是说:

*(v_ + vused_++)

后增量运算符在取消引用之前排序。因此,无论该调用发生什么,即使它抛出,vused_ 也会递增。因此,如果后续赋值抛出,这将违反强异常保证,因为 vused_ 将递增。这很容易说服自己:

void foo(int ) { throw std::runtime_error(""); }

int main() {
int ctr = 0;
try {
foo(ctr++);
}
except(...) { }

std::cout << ctr << std::endl; // prints 1
}

但是如果我们调用了foo(ctr); ctr++,它会打印 0。

关于c++ - 使用后递增索引的数组分配中的异常安全,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27470421/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com