0

Hello I've searched for iterator and reference invalidation of class string but I didn't find a result.

I have this code:

int main(){
    std::string s = "const char* manipulation in C++";
    auto beg = s.cbegin();
    auto& r = *s.begin();
    std::cout << s << std::endl;
    std::cout << "*beg: " << *beg << std::endl;
    std::cout << "r: " << r << std::endl;

    s.replace(beg, beg + 11, "string");
    std::cout << s << std::endl;
    std::cout << "*beg: " << *beg << std::endl;        
    std::cout << "r: " << r << std::endl;

}

The output:

const char* manipulation in C++
*beg: c
r: c
string manipulation in C++
*beg: s
r: s

It looks good but I don't know whether it is undefined behavior or not. Thank you!

Itachi Uchiwa
  • 3,044
  • 12
  • 26

2 Answers2

3

According to this reference:

Any iterators, pointers and references related to this object may be invalidated.

Aykhan Hagverdili
  • 28,141
  • 6
  • 41
  • 93
  • Ok. Thank you. So each reallocation invalidates all iterators and references and pointers? This is because of the memory locations being changed? – Itachi Uchiwa Sep 01 '19 at 19:58
  • 1
    Yes. When memory for contentious containers like `string` and `vector` has to be reallocated, all iterators and pointers are invalidated. – Aykhan Hagverdili Sep 01 '19 at 20:01
3

According to [string.require], it seems so:

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:

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

I believe that if you make the string smaller by replace, an implementation may decide to reduce the capacity, which would reallocate.

UPDATE

According to the C++11 Standard, the used overload of replace specifies only out_of_range exception. That would imply (?), that replace itself cannot reallocate and therefore it cannot change its capacity. Though, I am not sure if library functions may or may not throw exceptions that are not particularly specified.

In the referenced Draft, the relevant overload mentions also exceptions thrown by allocator's allocate member function, which implies the possibility of reallocation. I don't see any clause that would restrict this exception specification only to cases where the replacement causes enlargement of the original string.

Daniel Langr
  • 22,196
  • 3
  • 50
  • 93
  • Ok Thanks I got it now. I've created an empty string then tested for `capacity` which was `15` then I assign iterators and references then I called `replace ` passing in a const-character-string longer than capacity then I've tried to print references and iterators values. The result I got Assertion Dialog which means they've been invalidated. Thanks. – Itachi Uchiwa Sep 01 '19 at 19:56
  • 1
    But I've tested it on `C++14` and `replace` had caused re-allocation thus iterator, reference, pointer invalidation?! – Itachi Uchiwa Sep 01 '19 at 20:05
  • @ItachiUchiwa I don't have the C++14 Standard and the referenced Draft is much more complicated because your overload actually has the effect of the overload that involves `std::string_view`. In my tests, the capacity was not changed with GCC and Clang: https://wandbox.org/permlink/EzoybHNlpEdritNV. – Daniel Langr Sep 01 '19 at 20:07