2017-03-05 136 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()其初始化後發生的呼叫無效,並且輸出語句

相關問題