2017-03-05 140 views
1

Rust for C++ programmers切片6,有这样的代码:为什么我不能使用std :: vector元素的别名?

#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; 
} 

运行它,我得到:

g++ --std=c++11 main.cpp -I . -o main 
./main 
P▒▒o▒Y ▒▒2.▒8/.▒H/.▒H/.▒X/.▒X/.▒h/.▒h/.▒x/.▒x/.▒▒/. 
@▒▒ 
... 

它不断地去为更多的东西。我发现有关别名和载体,为一些问题:

  1. int vs const int&
  2. Changing things from a vector

但是,为什么别名不工作基础上他们,我无法弄清楚。我查看了关于矢量定义的http://en.cppreference.com/w/cpp/container/vector,但它似乎只是在磁盘上分配的内存。我明白Helloworld在程序的数据成员分配的地方,因为在这里上装配由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: 
... 

如果我不推的第二个元素world,该程序运行正常。那么为什么别名在第二次推后失去了对第一个向量元素的引用呢?

+0

浏览一下'push_back'页:http://en.cppreference.com/w/cpp/container/vector/push_back – chris

+1

等等,你读的幻灯片解释它。 – chris

+0

对不起,这是'push_back'文档中第一个说的。 '如果新的size()大于capacity(),那么所有迭代器和引用(包括过去末端迭代器)都将失效。“真正的问题是他们为什么要这样做。 – user

回答

4

当该方法push_back被称为矢量可以重新分配所使用的存储器和作为结果之前参考变为无效。

在向矢量添加新元素之前,您可以预留足够的内存。在这种情况下,参考将是有效的。例如

vector<string> v; 
v.reserve(2); 

v.push_back("Hello"); 

string& x = v[0]; 
v.push_back("world"); 

这里是一个示范项目

#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; 
} 

它的输出是

Hello world 
3

当你做第二次push_back迭代器和引用应该被认为是无效的。该矢量可能可能调整其数据块 - 很可能在另一个内存位置。

因为这样的变量引用x引用未分配的内存,随后导致未定义的行为。

2

push_back()调整矢量的大小(这是添加元素的内在因素)。

使所有引用该向量元素的迭代器,指针和引用无效。

通过无效的迭代器,指针或引用访问vector的元素(即在调整大小操作之前有效但不在之后)会导致未定义的行为。

x是由push_back()其初始化后发生的呼叫无效,并且输出语句

相关问题