2012-05-24 33 views
16

Khi bạn muốn truy cập std :: vector dưới dạng mảng C, bạn có thể chọn từ ít nhất bốn cách khác nhau, như bạn có thể thấy trong ví dụ này:std :: vector: vec.data() hoặc & vec [0]

#include <iostream> 
#include <vector> 

using namespace std; 

int main() { 
    std::vector<int> vec; 
    vec.push_back(1); 
    vec.push_back(2); 
    vec.push_back(42); 
    vec.push_back(24024); 
    { 
    int* arr = vec.data(); 
    cout << arr << endl; /* output: 0x9bca028 */ 
    cout << arr[3] << endl; /* output : 24024 */ 
    } 
    { 
    int* arr = &vec.front(); 
    cout << arr << endl; /* output: 0x9bca028 */ 
    cout << arr[3] << endl; /* output : 24024 */ 
    } 
    { 
    int* arr = &vec[0]; 
    cout << arr << endl; /* output: 0x9bca028 */ 
    cout << arr[3] << endl; /* output : 24024 */ 
    } 
    { 
    int* arr = &vec.at(0); 
    cout << arr << endl; /* output: 0x9bca028 */ 
    cout << arr[3] << endl; /* output : 24024 */ 
    } 
} 

Tôi đã tìm thấy trong hầu hết các trường hợp là &vec[0]. Tôi nghĩ đó là trang nhã nhất, vậy ... tại sao nó lại được sử dụng nhiều nhất? Có phải hiệu quả hơn hoặc tương thích hơn? Tôi không thể tìm thấy nhiều tài liệu về data().

+1

'dữ liệu()' * có thể được coi là không tương thích theo nghĩa là C++ 11 (giải thích tài liệu khan hiếm, vì nguồn tài liệu chính chỉ là bắt kịp với các tính năng mới), mặc dù thời gian chắc chắn sẽ làm cho sự không tương thích này biến mất và sau đó đó là cách xác định để đi. –

Trả lời

16

data() là thương hiệu mới với C++ 11, đó là lý do tại sao bạn không thấy nó thường xuyên. Ý tưởng sử dụng &vec.front() thậm chí không bao giờ xảy ra với tôi, có lẽ vì tôi sử dụng operator[] nhiều hơn thường xuyên hơn front() (hầu như không bao giờ). Tôi tưởng tượng nó cũng tương tự cho những người khác.

+0

Không phải là dữ liệu const? –

+0

@MooingDuck: Chỉ dành cho các vectơ const, [Tôi nghĩ] (http://en.cppreference.com/w/cpp/container/vector/data). Tôi sẽ kiểm tra nó ngay bây giờ. –

+7

@MooingDuck No. Nó đã được thêm vào chính xác để mọi người sẽ không phải viết: 'v.empty()? NULL: & v [0]'. – bames53

14

Nếu bạn đang sử dụng C++ 11, khi đó sử dụng data() chắc chắn là thích hợp hơn. Đặc biệt, nếu vectơ trống, thì việc sử dụng một trong hai tùy chọn còn lại sẽ mang lại hành vi không xác định! Nếu bạn không sử dụng C++ 11 và vectơ có thể trống, thì hãy đảm bảo kiểm tra điều kiện đó.

1

Trước khi C++ 11 std::array Tôi có thể nói rằng std::vector là vùng chứa phổ biến nhất được sử dụng thay cho mảng kiểu C. Toán tử [] thường ngụ ý truy cập thời gian không đổi, (tất cả là về số std::vector) và vì vậy hầu hết các trình lập trình thường chọn kiểu này để phản ánh truy cập và hành vi giống như mảng.

0

dữ liệu() đã là một phần của std::string trong một thời gian để bạn có thể đọc về điều đó. Tôi đã tìm thấy việc triển khai dữ liệu() trong std::vector tương tự. Thỉnh thoảng, tôi sử dụng dữ liệu() để xử lý std::string dưới dạng một mảng các byte thô.

4

Sử dụng & vec [0] là thông dụng nhất mặc dù, tôi đồng ý, trông hơi lạ. Một điều cần ghi nhớ cho tương lai. Nếu vectơ của bạn xảy ra là một vectơ của các đối tượng có lớp quá tải toán tử &(), hãy nhận ra rằng điều này sẽ gây ra hành vi lạ nếu bạn gọi & vec [0].

Điều này sẽ không nhận được địa chỉ xuất phát của mục đầu tiên trong mảng đối tượng liền kề bên trong, nó sẽ trả về bất cứ thứ gì vec [0] .operator &() sẽ trả về. Hầu hết nếu không phải tất cả thời gian, đó không phải là địa chỉ bạn đang tìm kiếm (sóng tay Jedi).

Một ví dụ điển hình về điều này là CComPtr của ATL. Nó quá tải nhà điều hành &() để lưu trữ nó trong một vector có thể có vấn đề. Để giải quyết vấn đề này, ATL có một lớp mẫu CAdapt có thể được sử dụng để ẩn toán tử &() trên CComPtr

+2

+1 cho vấn đề quá tải toán tử &() –

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