In this code:
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++;
}
we try to be exception safe and exception neutral. It is achieved by a means of having NewCopy()
helper function (that copies pointed memory and returns a pointer to a copied values) which follows these principles (we are not interested in that function here, it is exception safe & neutral). Lastly, all works because
v_[vused_] = t;
vused++;
we only change state of Stack if assignment does not throw. If we wrote
v_[vused_++] = t;
would the exception safety be violated? My guess is yes (postincrement operator returns old value but it does increment variable before return, and then after it returned the assignment is performed, so in case of exception the object state is invalid). But I might be mistaken (?)
From the standard, 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.
So when we call:
v_[vused_++]
which is to say:
*(v_ + vused_++)
The postincrement operator is sequenced before the dereference. Thus, regardless of what happens in that call, even if it throws, vused_
will be incremented. So this will violate the strong exception guarantee if the subsequent assignment throws since vused_
will be incremented. This is easy to convince yourself:
void foo(int ) { throw std::runtime_error(""); }
int main() {
int ctr = 0;
try {
foo(ctr++);
}
except(...) { }
std::cout << ctr << std::endl; // prints 1
}
But if we had called foo(ctr); ctr++
, it'd print 0.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With