2014-09-19 14 views
6

Gọi A là std::vector<double>,Số học con trỏ trên end() iterator

Điều này có được xác định rõ không?

if(!A.empty()) 
    std::vector<double>::iterator myBack = A.end() - 1; 

end iterator chỉ tốt cho sự bình đẳng và bất bình đẳng kiểm tra? Hoặc tôi có thể thực hiện một số số học con trỏ miễn là tôi vẫn còn trong container?

Trên nền tảng của tôi, mã này hoạt động. Tôi tự hỏi nếu điều này là di động.

+3

Điều này là tốt và bạn cũng có thể sử dụng 'A.rbegin()'. – perreal

+3

Nó là * số học * lặp. và nó sẽ là OK cho iterator hai chiều (như 'std :: vector :: iterator'). – Jarod42

Trả lời

5

Nó hoàn toàn hợp lệ vì vector::iterator là trình lặp truy cập ngẫu nhiên. Bạn có thể thực hiện các phép toán số học trên nó và nó không phụ thuộc vào nền tảng.

std::vector<double>::iterator it = A.end(); 
while (it != A.begin()){ 
    --it; //this will skip A.end() and loop will break after processing A.front() 
    //do something with 'it' 
} 

nhưng đề cập đến yếu tố lý thuyết quá khứ, vì vậy nó không trỏ đến phần tử và do đó sẽ không bị bỏ qua. Vì vậy, thực hành tốt nhất là sử dụng trình lặp ngược thay vì giảm dần trình lặp kết thúc.

for(std::vector<double>::reverse_iterator it = A.rbegin(); it != A.rend(); ++it) { 
    //do something with 'it' 
} 

Hai vòng làm điều tương tự, thứ hai là chỉ có thể hiểu được, cách sạch hơn để làm điều đó.

+0

Hai vòng lặp không giống nhau, vòng lặp đầu tiên không lặp qua 'A.front()'. – Jarod42

+1

Nhưng tôi không nghĩ rằng 'A.begin() - 1' là hợp lệ. – Jarod42

4

Đó là gần an toàn nếu bạn đều quan tâm đến một số trường hợp ngoại lệ:

A.end() mang đến cho bạn một iterator biểu thị vị trí ngay bên ngoài khi kết thúc std::vector. Bạn nên không phải cố gắng không quan tâm đến nó.

Nếu vectơ có 0 phần tử thì A.end() - 1không phải là được xác định rõ. Trong tất cả các trường hợp khác nó là và bạn thực sự có thể thực hiện số học con trỏ miễn là bạn đang ở trong giới hạn container. Lưu ý rằng tiêu chuẩn đảm bảo rằng dữ liệu std::vector tiếp giáp và được đóng gói chính xác giống như một mảng C++ của loại chứa. Ngoại lệ duy nhất là std::vector<bool> hoạt động khác nhau do chuyên môn đóng gói chặt chẽ theo tiêu chuẩn. (Lưu ý rằng sizeof(bool)không phải được đảm bảo để có giá trị cụ thể theo tiêu chuẩn).

Nếu tôi là bạn, tôi muốn sử dụng A.rbegin() để truy cập phần tử ngoài cùng bên phải và kiểm tra giá trị trả về trước khi tiếp tục và dính vào công thức lặp. Quá dễ để quên chuyên môn std::vector<bool>.

+0

Tôi không chắc chắn về trường hợp 'bool'. Không phải là biến lặp này - không phải con trỏ - arithmetics, như @ Jarod42 chỉ ra? Điều đó có nên làm cho nó hoàn toàn an toàn và được định nghĩa rõ ràng cho 'std :: vector '? –

+0

Nếu 'std :: vector ' có chính xác 3 phần tử thì tôi không tin rằng 'A.end() - 1' được định nghĩa nếu' sizeof (bool) == sizeof (int) '. Tôi có thể sai mặc dù. Nhưng nếu bạn bỏ bất cứ thứ gì vào 'bool *' thì bạn chắc chắn đang gặp rắc rối. Có lẽ toán tử quá tải trên trình lặp ngược ngược 'bool' sẽ xử lý vấn đề này. Câu trả lời ngắn gọn: Tôi không biết. Tôi đang nghĩ đến việc đặt một tiền thưởng cho câu hỏi này. – Bathsheba

+0

Nếu 'std :: vector :: iterator' đã hoạt động như bạn đang nói, lặp lại đơn giản trên vectơ sẽ không hoạt động. Miễn là bạn đang hoạt động trên các trình vòng lặp, '- 1' phải di chuyển nó thành một phần tử logic, không phải là các byte' sizeof (bool) '.Tôi đặt một số mã trên http://ideone.com/2pAiE1, và nó hoạt động như tôi mong đợi miễn là kết quả của phép trừ nằm trong vùng chứa. Bạn nên biên dịch nó bằng '_GLIBCXX_DEBUG' (hoặc tương đương với trình biên dịch của bạn) để có nó sủa vào bạn khi bạn vượt qua giới hạn. –

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