Làm thế nào để có được một phần tử nhất định trong một danh sách, đã cho vị trí?


92

Vì vậy, tôi có một danh sách:

list<Object> myList;
myList.push_back(Object myObject);

Tôi không chắc nhưng tôi tự tin rằng đây sẽ là phần tử "0" trong mảng. Có bất kỳ chức năng nào tôi có thể sử dụng sẽ trả về "myObject" không?

Object copy = myList.find_element(0);

?


8
Không có mảng - đó là một danh sách. Nếu bạn muốn lập chỉ mục theo số nguyên, tại sao bạn không sử dụng vectorthay thế?
Paul J. Lucas

2
Nếu bạn luôn muốn phần tử 0, hãy sử dụng front().
Paul J. Lucas

Tôi đã không kiểm tra này, nhưng tôi sẽ giả định myList.front () + num sẽ làm việc ở đây
Serguei Fedorov

2
@SergueiFedorov: không, không
Algoman

Câu trả lời:


129

Nếu bạn thường xuyên cần truy cập phần tử thứ N của một chuỗi, std::listđược triển khai dưới dạng danh sách được liên kết kép, có lẽ không phải là lựa chọn phù hợp. std::vectorhoặc std::dequecó thể sẽ tốt hơn.

Điều đó nói rằng, bạn có thể nhận được một trình lặp đến phần tử thứ N bằng cách sử dụng std::advance:

std::list<Object> l;
// add elements to list 'l'...

unsigned N = /* index of the element you want to retrieve */;
if (l.size() > N)
{
    std::list<Object>::iterator it = l.begin();
    std::advance(it, N);
    // 'it' points to the element at index 'N'
}

Đối với một vùng chứa không cung cấp quyền truy cập ngẫu nhiên, chẳng hạn như std::list, std::advancecác cuộc gọi operator++vào Nlần lặp lại . Ngoài ra, nếu việc triển khai Thư viện chuẩn của bạn cung cấp nó, bạn có thể gọi std::next:

if (l.size() > N)
{
    std::list<Object>::iterator it = std::next(l.begin(), N);
}

std::nextlà kết thúc một cách hiệu quả một lời gọi đến std::advance, giúp dễ dàng tăng Nthời gian trình lặp với ít dòng mã hơn và ít biến có thể thay đổi hơn. std::nextđã được thêm vào C ++ 11.


18
Trong khi bạn phải trả một hình phạt hiệu suất khi tìm kiếm danh sách được liên kết do thiếu quyền truy cập ngẫu nhiên, bạn sẽ phải trả một khoản phạt hiệu suất lớn hơn nhiều nếu bạn cần chèn hoặc xóa dữ liệu ở giữa vectơ hoặc deque. Câu hỏi không thực sự chứa đủ thông tin để quyết định xem họ có đang sử dụng vùng chứa lý tưởng cho mục đích của mình hay không.
tloach

1
Cần lưu ý rằng khi sử dụng std::advancehoặc std::next, có thể dễ dàng gọi UB. Không có giới hạn kiểm tra.
okovko

33

std::listkhông cung cấp bất kỳ chức năng nào để lấy phần tử được cung cấp một chỉ mục. Bạn có thể cố gắng lấy nó bằng cách viết một số mã, mà tôi không khuyên bạn nên sử dụng, vì điều đó sẽ không hiệu quả nếu bạn thường xuyên phải làm như vậy.

Những gì bạn cần là: std::vector. Sử dụng nó như:

std::vector<Object> objects;
objects.push_back(myObject);

Object const & x = objects[0];    //index isn't checked
Object const & y = objects.at(0); //index is checked 

7
std::list<Object> l; 
std::list<Object>::iterator ptr;
int i;

for( i = 0 , ptr = l.begin() ; i < N && ptr != l.end() ; i++ , ptr++ );

if( ptr == l.end() ) {
    // list too short  
} else {
    // 'ptr' points to N-th element of list
}

3

Có thể không phải là cách hiệu quả nhất. Nhưng bạn có thể chuyển đổi danh sách thành một vector.

#include <list>
#include <vector>

list<Object> myList;

vector<Object> myVector(myList.begin(), myList.end());

Sau đó, truy cập vector bằng toán tử [x].

auto x = MyVector[0];

Bạn có thể đặt nó trong một hàm trợ giúp:

#include <memory>
#include <vector>
#include <list>

template<class T>
shared_ptr<vector<T>> 
ListToVector(list<T> List) {
shared_ptr<vector<T>> Vector {
        new vector<string>(List.begin(), List.end()) }
return Vector;
}

Sau đó, sử dụng funciton trợ giúp như thế này:

auto MyVector = ListToVector(Object);
auto x = MyVector[0];
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.