On the slide 6 at Rust for C++ programmers, there is this code:
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int main()
{
vector<string> v;
v.push_back("Hello");
string& x = v[0];
v.push_back("world");
cout << x << endl;
return 0;
}
Running it I got:
g++ --std=c++11 main.cpp -I . -o main
./main
P▒▒o▒Y ▒▒2.▒8/.▒H/.▒H/.▒X/.▒X/.▒h/.▒h/.▒x/.▒x/.▒▒/.
@▒▒
...
And it keeps going for much more stuff. I found some question about aliases and vectors as:
But I could not figure out why the alias is not working based on them. I looked over the http://en.cppreference.com/w/cpp/container/vector, about the vector definition, however it does just seem to be continue memory allocated on the disk. I understand the string Hello
and world
are allocated somewhere on the data member of the program, as on the assembly here by g++ main.cpp -S
:
...
.lcomm _ZStL8__ioinit,1,1
.def __main; .scl 2; .type 32; .endef
.section .rdata,"dr"
.LC0:
.ascii "Hello\0"
.LC1:
.ascii "world\0"
.text
.globl main
.def main; .scl 2; .type 32; .endef
.seh_proc main
main:
...
If I do not push the second element world
, the program correctly runs. Therefore why the alias is loosing the reference to the first vector element after the second push?
When the method push_back
was called the vector can reallocate the used memory and as result the reference becomes invalid.
You could reserve enough memory before adding new elements to the vector. In this case the reference will be valid. For example
vector<string> v;
v.reserve( 2 );
v.push_back("Hello");
string& x = v[0];
v.push_back("world");
Here is a demonstrative program
#include <iostream>
#include <vector>
#include <string>
int main()
{
std::vector<std::string> v;
v.reserve( 2 );
v.push_back("Hello");
std::string& x = v[0];
v.push_back("world");
std::cout << x << ' ' << v[1];
std::cout << std::endl;
return 0;
}
Its output is
Hello world