I am new to C++ programming but have programmed in higher-level languages to find my way around most documentation. I'm learning about exception handling in C++, specifically with this example:
vector<int> myNums;
try
{
myNums.resize(myNums.max_size() + 1);
}
catch (const bad_alloc& err)
{
cout << err.what() << endl;
}
This code doesn't catch the exception because the exception thrown by the .resize() method isn't bad_alloc
; it's a length_error
. So, from this documentation, how do you get to that? Maybe I missed something obvious.
https://cplusplus.com/reference/vector/vector/resize/
The only specific exception mentioned in there is bad_alloc
. Can someone walk me through how you'd get to know that length_error
is the right exception starting from that page?
This is not uncommon. The complexity of the language has increased so much over the years, accumulating multiple revisions to the C++ standard, that even the C++ standard itself can be at odds with itself, sometimes.
Let's just see what the C++ standard itself says about two versions of the overloaded resize()
vector method. I happen to have a copy of N4860 handy which is, basically, the C++20 version, and while looking up what the C++ standard itself says about resize()
's exceptions, I found that the two resize()
overloads define their exception behavior as follows:
constexpr void resize(size_type sz);
// ...
Remarks: If an exception is thrown other than by the move constructor of a non-Cpp17CopyInsertable T there are no effects.
// ...
constexpr void resize(size_type sz, const T& c);
// ...
Remarks: If an exception is thrown there are no effects.
That's the only mention of exceptions in resize()
. I found nothing on a more general in vector
itself, nor in "Container Requirements", there was some discussion of exception guarantees but none pertaining to the specific details of vector's resize()
or reserve()
.
This is an obvious oversight. It's fairly obvious that when it comes to exceptions that might be generated as a result of reallocations, both overloads should have the same exception behavior. The first overload's description is lifted straight from reserve()
that just precedes it. It goes without saying that resize()
uses reserve()
to grow the vector's capacity, when needed, and inherits its exception guarantees/behavior.
But the same thing must be true with the 2nd resize()
overload. The only difference between them is that one default-constructs new values when the vector grows and the other one copy-constructs. But in terms of exception behavior during reallocation they must be identical. The total overall difference, related to exceptions, between the two overloads is due to any exception differences between the value's default constructor and/or its copy/move constructors.
My question is, from looking at this documentation, how do you get to that? > Maybe I missed something obvious.
No, you did not miss anything. The C++ standard itself has some gaps; not to mention 2nd-hand sources of documentation like the one you're looking at.
You get where you want to go by studying everything about the class, template, or algorithm in question, understanding how it must work -- i.e. the resize()
s inheriting certain parts of their behavior from reserve()
-- and then drawing the inescapable inferences.
TLDR: it is what it is.
Starting with https://cplusplus.com/reference/vector/vector/resize/, if you've got a case like yours pushing max_size()
, you might pay special attention to the case listed on this doc page which states:
If n is also greater than the current container capacity, an automatic reallocation of the allocated storage space takes place.
Since your case is absolutely going to be greater than the current container capacity, this might be worth looking into. Linked in this chunk of text is the doc page for capacity: https://cplusplus.com/reference/vector/vector/capacity/. From the capacity page, you would read that vector::reserve
is used for explicitly increasing the capacity of the vector. Since your case with max_size() + 1
is certainly going to involve increasing vector capacity, you might suspect this function is involved. So you might go to the doc page: https://en.cppreference.com/w/cpp/container/vector/reserve
Here you would read that vector::reserve
takes a parameter new_cap
which determines the new capacity of a vector. It throws length_error
when new_cap > max_size()
.
I give this series of steps not because I think anyone would/should be expected to dig this much through docs every time they write code. Only because you were curious what steps might have led you to the exception that was thrown.
I agree it would be much better if the documentation for resize
just covered all it's bases with regards to which exceptions get thrown in all cases. Unfortunately, this is all too common with regards to documentation.
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