void append(int x) {
if (size >= capacity) {
capacity = 2 * capacity; // double the capacity
int* new_arr = newint[capacity]; // make new underlying array
// twice size of old one
for(int i = 0; i < size; ++i) { // copy elements of v
new_arr[i] = arr[i]; // into new_arr
}
delete[] arr; // delete old arr
arr = new_arr; // assign new_arr
}
// What happens after here ?
assert(size < capacity);
arr[size] = x;
size++;
}
You've double-posted this. On line 17 if size is greater than or equal to capacity, the program is aborted. This could conceivably happen if line 3 resulted in overflow, in which case the loop on line 7-9 would result in undefined behavior prior to the sanity check, although I would expect line 4 would probably result in an exception being thrown prior to that happening.
#include <iostream>
#include <cassert>
int main()
{
int a{}, b{};
std::cin >> a >> b;
assert(a > b);
}
//Output
/*
1
2
Assertion failed: a > b, file test0.cpp, line 8
This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.
Process returned 255 (0xFF) execution time : 6.629 s
Press any key to continue.*/
if( size >= capacity and NDEBUG is not defined ) then abort the program with a diagnostic message
else carry on normally with the next statement
An assertion is simply a logical expression that is assumed to be true. However, for an assertion to be more than a comment, we need a way of expressing what happens if it is false.
...
In <cassert>, the standard library provides the assert(A) macro, which checks its assertion, A ,
at run time if and only if the macro NDEBUG ("not debugging") is not defined. If the assertion fails, the compiler writes out an error message containing the (failed) assertion, the source file name, and the source file line number and terminates the program.
Stroustrup in 'The C++ Programming language (4th ed.)'
void append(int x) {
if (size >= capacity) { // if there is not enough space allocated to add one more item
/*
// this sequence of operations is not exception safe
// new int[capacity]; may throw and we would be saddled with an invalid capacity
capacity = 2 * capacity; // double the capacity
int* new_arr = new int[capacity]; // make new underlying array
// twice size of old one
*/
// we assume that the current value of capacity is non-zero (ie. it is some positive number)
// so that if we create a buffer of size (capacity*2), it would be a larger number
// we can assert the assumption made while writing the code. if the assertion fails
// (if capacity == 0), capacity*2 is also zero, and our code is broken
// very robust check may include a check to see if we can safely double the capacity.
// if( capacity < std::numeric_limits<std::size_t>::max()/2 ) ;
assert( capacity > 0 ) ;
// try to make a new array twice the size of old one
// this may throw bad_alloc or bad_array_new_length
int* new_arr = newint[capacity*2];
// allocation was successful, update capacity to reflect it
capacity = 2 * capacity;
for(int i = 0; i < size; ++i) { // copy elements of v
new_arr[i] = arr[i]; // into new_arr
}
delete[] arr; // delete old arr
arr = new_arr; // assign new_arr
}
// if the code is correct up to this point, it should be possible
// to append an item at the end without allocating a larger chunk of memory.
// we write the rest of the code under the assumption that this assumption is true
// if our assumption is wrong, the assertion fails (debug), and we get to know
// that there is an error somewhere in our code; it needs to be fixed
assert(size < capacity);
arr[size] = x; // add the new item at the end
size++; // increment size
}