2009-09-07 51 views
6

Khi sử dụng vùng chứa C++ STL, trong điều kiện nào phải tham chiếu giá trị được truy cập? Ví dụ: có bất kỳ tham chiếu nào bị vô hiệu sau khi cuộc gọi hàm tiếp theo tới vùng chứa không?Tài liệu tham khảo liên tục trong Vùng chứa STL

{ 
std::vector<int> vector; 
vector.push_back (1); 
vector.push_back (2); 
vector.push_back (3); 

vector[0] = 10;  //modifies 0'th element 

int& ref = vector[0]; 
ref = 10;    //modifies 0'th element 

vector.push_back (4); 
ref = 20;    //modifies 0'th element??? 

vector.clear(); 
ref = 30;    //clearly obsurd 
} 

Tôi hiểu rằng trong hầu hết các triển khai của stl, điều này sẽ hiệu quả, nhưng tôi quan tâm đến những tuyên bố tiêu chuẩn yêu cầu. Im --edit: Im quan tâm vì tôi muốn thử thư viện STXXL (http://stxxl.sourceforge.net/) cho C++, nhưng tôi nhận ra rằng các tham chiếu được trả về bởi các thùng chứa không liên tục qua nhiều lần đọc, và do đó không tương thích mà không thực hiện thay đổi (Tuy nhiên bề ngoài) với mã stl hiện tại của tôi. Một ví dụ:

{ 
std::vector<int> vector; 
vector.push_back (1); 
vector.push_back (2); 


int& refA = vector[0]; 
int& refB = vector[1]; //refA is not gaurenteed to be valid anymore 
} 

Tôi chỉ muốn biết nếu điều này có nghĩa là container STXXL nơi tương thích không phải là 100%, hoặc thực sự nếu tôi đã sử dụng STL container một cách phụ thuộc không an toàn/thực hiện trong suốt thời gian.

+2

Tôi tìm thấy câu trả lời có liên quan về Câu hỏi thường gặp của họ http://algo2.iti.uni-karlsruhe.de/dementiev/stxxl/trunk/FAQ.html "Bạn không được chuyển hoặc lưu trữ tham chiếu đến các phần tử trong cấu trúc dữ liệu bộ nhớ ngoài Khi tham chiếu được sử dụng, khối chứa phần tử có thể không còn trong bộ nhớ trong. ", Vì vậy câu trả lời là KHÔNG, tham chiếu đến các phần tử vùng chứa để không có hành vi giống như các đối tác STL của chúng. – Akusete

+1

Nhìn qua tiêu chuẩn C++, tất cả các thùng chứa có tham số 'tham số',' const_reference', 'pointer' và' const_pointer' được đặt thành typedefs tương ứng từ trình cấp phát cơ bản. Dường như ủy ban tiêu chuẩn ban đầu muốn thiết lập một trừu tượng cho các ref và con trỏ sao cho ngay cả những thứ này có thể được "quản lý" bởi một container (theo cách mà các trình vòng lặp đã có) bằng proxy, nhưng dừng lại một phần - tiêu chuẩn bắt buộc rằng các loại 'cấp phát :: con trỏ' được' T * 'vv, làm cho typedefs mình cuối cùng vô nghĩa tôi nghĩ. –

+0

Tôi có cảm giác tương tự bằng cách đọc qua các giao diện của hầu hết các container STL, nhưng tôi không thể tìm thấy một cuộc thảo luận về lý do tại sao họ chỉ đi một nửa. – Akusete

Trả lời

12

Về chèn vào vector, tiêu chuẩn nói trong 23.2.4.3/1:

[insert()] gây tái phân bổ nếu kích thước mới lớn hơn công suất cũ . Nếu không có sự tái phân bổ xảy ra, tất cả các vòng lặp và tham chiếu trước khi điểm chèn vẫn giữ nguyên là .

(Mặc dù điều này trên thực tế này nói về insert(), Bảng 68 chỉ ra rằng a.push_back(x) phải tương đương với a.insert(a.end(), x) cho bất kỳ vector a và giá trị so x.) Điều này có nghĩa là nếu bạn reserve() đủ bộ nhớ trước, thì (và chỉ sau đó) trình vòng lặp và tham chiếu được đảm bảo không bị vô hiệu khi bạn insert() hoặc push_back() mục khác.

Về mục gỡ bỏ, 23.2.4.3/3 nói:

[erase()] làm mất hiệu lực tất cả các lặp và tài liệu tham khảo sau khi điểm của xóa.

Theo Bảng 68 và Bảng 67 tương ứng, pop_back()clear() tương đương với các cuộc gọi thích hợp tới erase().

+0

damn, tôi đoán nó là không thể thực hiện 100% STL tương thích thực hiện các container được hỗ trợ đĩa. – Akusete

+1

Tôi đoán là không, nếu bạn muốn cho phép các tham chiếu được tự do thực hiện và được giữ lại. Nhưng với tâm trí của tôi, việc giữ các tham chiếu dài hạn tới các mục nằm trong cấu trúc dữ liệu khác là một thực hành "hèn nhát" - có lý do tại sao bạn không thể chỉ giữ các vòng lặp thay thế không? –

+0

Nếu tôi muốn thực hiện nhiều thay đổi đối với cấu trúc trong vùng chứa, tôi thường (có thể là thực hành không tốt) lấy tham chiếu về nó, sau đó sửa đổi tham chiếu. Nó là effiecent hơn truy cập nó thông qua các container mỗi lần (đặc biệt là với các container dựa trên cây) và neater hơn so với lấy một bản sao địa phương và viết lại sau đó. ... bởi vì nó là một habbit, và theo hiểu biết tốt nhất của tôi một cách sử dụng hợp lệ các tham chiếu, tôi đã mệt mỏi khi sử dụng một thư viện mà sử dụng sẽ gây ra lỗi nghiêm trọng (cũng sẽ không thể phát hiện được) – Akusete

1

Tôi hy vọng rằng tham chiếu sẽ bị vô hiệu hóa chỉ bởi bất kỳ rõ ràng hoặc ngụ ý resize() (xem thêm các phương pháp max_size, capacityreserve).

+0

Đồng ý. Tại sao xóa() làm mất hiệu lực bộ nhớ? Nó sẽ chỉ đơn giản là đặt nó thành null hoặc tương tự. – jkeys

+0

@Hooked: Không thể di chuyển dựa trên hành vi đó. Việc thực hiện thư viện chuẩn C++ là miễn phí để làm bất cứ điều gì nó muốn, miễn là nó tuân thủ các quy tắc ngữ nghĩa được trình bày trong tiêu chuẩn ISO C++ ISO 2003. –

1

Vector sẽ vô hiệu hóa trình lặp và tham chiếu của nó khi nó phân bổ lại, phụ thuộc vào khả năng hiện tại của nó. Mặc dù mã trên có thể hoạt động trong một số trường hợp, bạn không nên dựa vào điều này vì tham chiếu có thể bị vô hiệu sau cuộc gọi push_back (4).

7

Một số quy tắc cơ bản cho vector:

  • Tái phân bổ làm mất hiệu lực tất cả các tài liệu tham khảo , con trỏ, và lặp cho các yếu tố của vectơ.
  • Insertions có thể tham chiếu không hợp lệ, con trỏ và trình lặp.
  • Chèn hoặc xóa các phần tử làm mất hiệu lực tham chiếu, con trỏ và trình lặp tham chiếu đến các yếu tố sau .
  • Nếu chèn gây ra phân bổ lại, nó sẽ vô hiệu hóa tất cả các tham chiếu, trình lặp và con trỏ.
+1

* Nếu bạn đã dành đủ không gian, thì việc bố trí lại được đảm bảo không xảy ra khi chèn (có thể là hiển nhiên nhưng quan trọng). –

Các vấn đề liên quan