[英]Why I cannot take a alias to a std::vector element?
On the slide 6 at Rust for C++ programmers , there is this code: 在Rust为C ++程序员准备的幻灯片6上,有以下代码:
#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.
我查看了有关向量定义的http://en.cppreference.com/w/cpp/container/vector ,但是它似乎只是继续在磁盘上分配的内存。 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
: 我知道字符串
Hello
和world
分配在程序数据成员的某个位置,如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. 如果我不推动第二个元素
world
,该程序将正确运行。 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. 调用方法
push_back
时,向量可以重新分配已使用的内存,结果引用无效。
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
When you do the second push_back iterators and references should be assumed to be invalidated. 当您执行第二个push_back迭代器和引用时,应假定其无效。 The vector may probably resize its data block - most likely at another memory location.
向量可能会调整其数据块的大小-最有可能在另一个内存位置。
As such the variable reference x is referencing unallocated memory which subsequently leads to undefined behavior. 这样,变量引用x引用了未分配的内存,这随后导致未定义的行为。
push_back()
resizes the vector (that's intrinsic in adding an element to it). push_back()
调整向量的大小(在向其中添加元素时是固有的)。
That invalidates all iterators, pointers, and references that refer to elements of that vector. 这会使所有引用该向量元素的迭代器,指针和引用无效。
Accessing elements of a vector through an invalidated iterator, pointer, or reference (ie that were valid before the resizing operation, but not after) gives undefined behaviour. 通过无效的迭代器,指针或引用访问向量的元素(即在调整大小操作之前有效,但在大小调整操作之后无效)会产生不确定的行为。
x
is invalidated by the call of push_back()
that occurs after its initialisation, and before the output statement x
在初始化之后和输出语句之前通过push_back()
调用而无效
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.