2009-03-13 38 views
51

Tôi có một vectơ myObject trong phạm vi toàn cục. Tôi có phương pháp sử dụng một số std::vector<myObject>::const_iterator để duyệt qua vectơ và thực hiện một số so sánh để tìm một phần tử cụ thể. Khi tôi đã tìm thấy phần tử được yêu cầu, tôi muốn có thể trả về một con trỏ tới nó (vectơ tồn tại trong phạm vi toàn cục).Trả về một con trỏ tới phần tử vectơ trong C++

Nếu tôi trả lại &iterator, tôi có trả lại địa chỉ của trình lặp hoặc địa chỉ của những gì trình vòng lặp trỏ tới không?

Tôi có cần phải đúc const_iterator quay lại myObject, sau đó trả lại địa chỉ đó không ??

+0

tôi đề nghị bạn đọc bài viết này từ Scott Meyers về việc sử dụng lặp: http://www.ddj.com/cpp/184401406 Ông đưa ra hướng dẫn về chuyển đổi const_iterator để iterator vv –

Trả lời

74

Return địa chỉ trong những điều được trỏ đến bởi iterator:

&(*iterator) 

Edit: Để làm sáng tỏ một số nhầm lẫn:

vector <int> vec;   // a global vector of ints 

void f() { 
    vec.push_back(1); // add to the global vector 
    vector <int>::iterator it = vec.begin(); 
    * it = 2;    // change what was 1 to 2 
    int * p = &(*it);  // get pointer to first element 
    * p = 3;    // change what was 2 to 3 
} 

Không cần vectơ của con trỏ hoặc phân bổ động.

+60

Tôi không nghĩ rằng đó là một ý tưởng tốt để trả lại con trỏ đến đối tượng được lưu trữ trong vectơ. Điều gì sẽ xảy ra nếu ai đó vector thực hiện push_back() sau khi chúng ta có được con trỏ. Các vector có thể thay đổi kích thước và con trỏ có thể trở thành không hợp lệ, phải không? – Naveen

+1

Chính xác như vậy cũng đúng cho các trình vòng lặp. –

+3

Vâng, đó là lý do tại sao tôi tin rằng cách an toàn nhất là trả lại bản sao. – Naveen

3

Không phải là ý tưởng hay để trả về trình lặp. Các Iterator trở nên không hợp lệ khi các sửa đổi đối với vectơ (đảo ngược \ xoá) xảy ra. Ngoài ra, các iterator là một đối tượng địa phương được tạo ra trên stack và do đó trở về địa chỉ của cùng là không phải ở tất cả an toàn. Tôi muốn đề nghị bạn làm việc với myObject hơn là các trình vòng lặp vector.

CHỈNH SỬA: Nếu đối tượng có trọng lượng nhẹ thì tốt hơn bạn nên trả lại đối tượng. Các con trỏ ngược lại khác tới myObject được lưu trữ trong vectơ.

0

Say, bạn phải như sau:

std::vector<myObject>::const_iterator first = vObj.begin(); 

Sau đó, đối tượng đầu tiên trong vector là: *first. Để nhận địa chỉ, hãy sử dụng: &(*first).

Tuy nhiên, để phù hợp với thiết kế STL, tôi khuyên bạn nên trả lại một trình lặp thay vì nếu bạn dự định chuyển nó sau này sang các thuật toán STL.

+0

Tôi muốn trả về một con trỏ tới myObject trong vectơ ... việc thực hiện cách con trỏ đó được tìm thấy thay đổi của tôi, vì thế tôi không muốn trả về một trình lặp. – Krakkos

12

Trả về & trình lặp sẽ trả về địa chỉ của trình lặp. Nếu bạn muốn trả về cách đề cập đến phần tử, hãy trả về bản thân trình vòng lặp.

Hãy coi chừng rằng bạn không cần vectơ là toàn cầu để trả về trình lặp/con trỏ, nhưng các hoạt động đó trong vectơ có thể làm mất hiệu lực trình lặp. Thêm các phần tử vào vectơ, ví dụ, có thể di chuyển các phần tử vectơ đến một vị trí khác nếu kích thước mới() lớn hơn bộ nhớ được dành riêng. Việc xóa một phần tử trước phần tử đã cho từ vectơ sẽ làm cho trình vòng lặp tham chiếu đến một phần tử khác.

Trong cả hai trường hợp, tùy thuộc vào việc triển khai STL, có thể khó gỡ lỗi chỉ với các lỗi ngẫu nhiên xảy ra thường xuyên.

EDIT sau khi bình luận: 'có, tôi không muốn trả về trình lặp a) vì const của nó và b) chắc chắn nó chỉ là một trình lặp tạm thời cục bộ?- Krakkos '

Bộ lặp không ít nhiều cục bộ hoặc tạm thời hơn bất kỳ biến nào khác và chúng có thể sao chép được. Bạn có thể trả lại nó và trình biên dịch sẽ tạo bản sao cho bạn vì nó sẽ có con trỏ.

Bây giờ với const-ness. Nếu người gọi muốn thực hiện các sửa đổi thông qua phần tử trả về (cho dù là con trỏ hay trình vòng lặp) thì bạn nên sử dụng một trình lặp không-const. (Chỉ cần xóa 'const_' khỏi định nghĩa của trình lặp).

+0

có, tôi không muốn trả về trình lặp a) bởi vì const của nó và b) chắc chắn nó chỉ là một trình lặp tạm thời cục bộ? – Krakkos

0

Bạn đang lưu trữ các bản sao của myObject trong vectơ. Vì vậy, tôi tin rằng việc sao chép thể hiện của myObject không phải là một hoạt động tốn kém. Sau đó, tôi nghĩ rằng an toàn nhất sẽ được trả lại một bản sao của myObject từ chức năng của bạn.

+0

Tôi cần thay đổi một số thuộc tính của myObject được trả lại, vì vậy không muốn tạo bản sao ... bằng cách sử dụng phương thức con trỏ, tôi có thể chỉnh sửa chúng trực tiếp. – Krakkos

3

Chừng nào vector của bạn vẫn còn trong phạm vi toàn cầu, bạn có thể quay trở lại:

&(*iterator) 

tôi sẽ cảnh cáo bạn rằng đây là khá nguy hiểm nói chung. Nếu vectơ của bạn được chuyển ra khỏi phạm vi toàn cục và bị hủy, mọi con trỏ tới myObject sẽ không hợp lệ. Nếu bạn đang viết các hàm này như là một phần của một dự án lớn hơn, việc trả về một con trỏ không phải là const có thể khiến ai đó xóa giá trị trả về. Điều này sẽ không xác định, và thảm họa, các hiệu ứng trên ứng dụng.

tôi muốn viết lại này như:

myObject myFunction(const vector<myObject>& objects) 
{ 
    // find the object in question and return a copy 
    return *iterator; 
} 

Nếu bạn cần phải sửa đổi myObject trở lại, lưu trữ giá trị của bạn như con trỏ và phân bổ chúng trên heap:

myObject* myFunction(const vector<myObject*>& objects) 
{ 
    return *iterator; 
} 

Bằng cách đó bạn có kiểm soát khi họ bị hủy.

Something như thế này sẽ phá vỡ ứng dụng của bạn:

g_vector<tmpClass> myVector; 

    tmpClass t; 
    t.i = 30; 
    myVector.push_back(t); 

    // my function returns a pointer to a value in myVector 
    std::auto_ptr<tmpClass> t2(myFunction()); 
+0

Sử dụng auto_ptr trong một con trỏ tới một đối tượng được lưu trữ trong toàn cầu giống như tự bắn mình vào chân. Tôi đồng ý rằng rất nguy hiểm khi trả về một con trỏ tới một đối tượng mà toàn bộ thời gian của nó có thể thay đổi, nhưng mẫu của bạn cũng không thực tế. – Ismael

1

Bạn có thể sử dụng dữ liệu chức năng của vector:

Trả về một con trỏ đến phần tử đầu tiên trong vector.

Nếu không muốn các con trỏ đến phần tử đầu tiên, nhưng theo chỉ số, sau đó bạn có thể thử, ví dụ:

//the index to the element that you want to receive its pointer: 
int i = n; //(n is whatever integer you want) 

std::vector<myObject> vec; 
myObject* ptr_to_first = vec.data(); 

//or 

std::vector<myObject>* vec; 
myObject* ptr_to_first = vec->data(); 

//then 

myObject element = ptr_to_first[i]; //element at index i 
myObject* ptr_to_element = &element; 
0

Tham khảo của dirkgently và câu trả lời anon, bạn có thể gọi trước chức năng thay vì bắt đầu chức năng, vì vậy bạn làm không phải viết *, nhưng chỉ &.

Mã số Ví dụ:

vector<myObject> vec; //You have a vector of your objects 
myObject first = vec.front(); //returns reference, not iterator, to the first object in the vector so you had only to write the data type in the generic of your vector, i.e. myObject, and not all the iterator stuff and the vector again and :: of course 
myObject* pointer_to_first_object = &first; //* between & and first is not there anymore, first is already the first object, not iterator to it. 
0

Tôi không chắc chắn nếu trả lại địa chỉ của người điều trỏ bởi iterator là cần thiết. Tất cả những gì bạn cần là chính con trỏ. Bạn sẽ thấy lớp lặp của STL tự thực hiện việc sử dụng _Ptr cho mục đích này.Vì vậy, chỉ cần làm:

return iterator._Ptr; 
Các vấn đề liên quan