Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does the standard guarantee that string::erase and string::pop_back DO NOT reallocate memory?

Tags:

c++

string

Does the standard guarantee that string::erase and string::pop_back DO NOT reallocate memory? After erasing some elements, is it possible that the string might be shrink automatically?

I checked the standard, it says that string::erase and string::pop_back either throw std::out_of_range or throw nothing. Can I take that as a guarantee that these methods DO NOT do any reallocation? Since the reallocation might throw bad_alloc.

like image 712
for_stack Avatar asked Aug 29 '17 08:08

for_stack


2 Answers

No, sensible implementations might not reallocate but the standard does not guarantee that these method calls do not reallocate, the standard says on the requirements:

References, pointers, and iterators referring to the elements of a basic_­string sequence may be invalidated by the following uses of that basic_­string object:

(4.1) as an argument to any standard library function taking a reference to non-const basic_­string as an argument.227

(4.2) Calling non-const member functions, except operator[], at, data, front, back, begin, rbegin, end, and rend.

Both proposed methods fall under category 2 and thus both might change capacity() which would implicitly mean a reallocation.

pop_back is required to have the same effect as erase as erase is specified as :

Effects: Determines the effective length xlen of the string to be removed as the smaller of n and size() - pos. 3

The function then replaces the string controlled by *this with a string of length size() - xlen whose first pos elements are a copy of the initial elements of the original string controlled by *this, and whose remaining elements are a copy of the elements of the original string controlled by *this beginning at position pos + xlen.

There's no guarantee on how that copy is made, extra allocations or reallocations are thus possible.


As for

Can I take that as a guarantee that these methods DO NOT do any reallocation? Since the reallocation might throw bad_alloc.

The standard does not seem to explicitly mention the possibility of a bad_alloc caused by any of the methods. Even with a binding reserve call there is no mention of it:

void reserve(size_type res_arg=0);

Throws: length_­error if res_­arg > max_­size()

Thus I don't think that assumption can be made.

like image 124
Hatted Rooster Avatar answered Sep 29 '22 10:09

Hatted Rooster


Yes, you may assume that the Throws: on these functions prohibits reallocation (which could throw bad_alloc).

20.5.5.12 Restrictions on exception handling [res.on.exception.handling]

Any of the functions defined in the C++ standard library can report a failure by throwing an exception of a type described in its Throws: paragraph, or of a type derived from a type named in the Throws: paragraph that would be caught by an exception handler for the base type.

...

Functions defined in the C++ standard library that do not have a Throws: paragraph but do have a potentially- throwing exception specification may throw implementation-defined exceptions.186 Implementations should report errors by throwing exceptions of or derived from the standard exception classes (21.6.3.1, 21.8, 22.2).

Note that the spec does not explicitly say that something marked with a "Throws: Nothing." can't throw anything. But at some point common sense has to take over. The standard also doesn't explicitly state that these functions can't reformat your disk. In general the standard specifies what the functions can do, and they are not allowed to do anything else.

The only way a function throws an exception not listed in the Throws: spec (or a derived type) is if the client uses it in a way that invokes undefined behavior.

like image 38
Howard Hinnant Avatar answered Sep 29 '22 11:09

Howard Hinnant