2012-01-15 50 views
8

Tôi đã tìm kiếm về chủ đề này và tôi thấy rất nhiều cách để chuyển đổi một mảng [] để một std :: vector, như sử dụng:Sao chép một mảng thành một std :: vector

assign(a, a + n) 

hoặc trực tiếp tại các nhà xây dựng:

std::vector<unsigned char> v (a, a + n); 

những giải quyết vấn đề của tôi, nhưng tôi tự hỏi nếu nó là có thể (và chính xác) để thực hiện:

myvet.resize(10); 
memcpy(&myvet[0], buffer, 10); 

tôi tự hỏi này bởi vì tôi có đoạn mã sau:

IDiskAccess::ERetRead nsDisks::DiskAccess::Read(std::vector<uint8_t>& bufferRead, int32_t totalToRead) 
{ 
    uint8_t* data = new uint8_t[totalToRead]; 
    DWORD totalRead; 
    ReadFile(mhFile, data, totalToRead, &totalRead, NULL); 
    bufferRead.resize(totalRead); 
    bufferRead.assign(data, data + totalRead); 
    delete[] data; 

    return IDiskAccess::READ_OK; 
} 

Và tôi muốn làm:

IDiskAccess::ERetRead nsDisks::DiskAccess::Read(std::vector<uint8_t>& bufferRead, int32_t totalToRead) 
{ 
    bufferRead.resize(totalToRead); 
    DWORD totalRead; 
    ReadFile(mhFile, &bufferRead[0], totalToRead, &totalRead, NULL); 
    bufferRead.resize(totalRead); 

    return IDiskAccess::READ_OK; 
} 

(Tôi đã gỡ bỏ điều trị lỗi của hàm ReadFile để đơn giản hóa các bưu điện).

Nó đang hoạt động, nhưng tôi e rằng nó không an toàn. Tôi tin rằng nó là ok, như bộ nhớ được sử dụng bởi các vector là liên tục, nhưng tôi đã không bao giờ nhìn thấy một người nào đó bằng cách sử dụng vectơ theo cách này.

Có đúng không khi sử dụng các vectơ như thế này? Có lựa chọn nào khác tốt hơn không?

Trả lời

8

Có an toàn không với tiêu chuẩn std::vector C++ đảm bảo rằng các phần tử sẽ được lưu trữ tại các vị trí bộ nhớ tiếp giáp.

C++ 11 Tiêu chuẩn:

23.3.6.1 Lớp tổng quan templatevector [vector.overview]

Một vector là một container chuỗi hỗ trợ lặp truy cập ngẫu nhiên. Ngoài ra, các hoạt động chèn và xóa thời gian liên tục (phân bổ) ở cuối; chèn và xóa ở giữa thời gian tuyến tính. Quản lý lưu trữ được xử lý tự động, mặc dù các gợi ý có thể được đưa ra để cải thiện hiệu quả. Các phần tử của véc tơ được lưu giữ liền kề, có nghĩa là ifv là avector nơiT là một số loại khác với bool, sau đó nó tuân theo định danh & v [n] == & v [0] + n cho all0 < = n < v .kích thước().

1

Thay đổi kích thước của bạn trước tiên và nó sẽ hoạt động tốt.

vector<int> v; 
v.resize(100); 
memcpy(&v[0], someArrayOfSize100, 100 * sizeof(int)); 
+3

Anh * * thay đổi kích thước đầu tiên (xem dòng đầu tiên của hàm). – celtschk

+1

Tôi đã không ngụ ý rằng ông đã không làm như vậy. Tôi chỉ nhấn mạnh tầm quan trọng của nó. – TheBuzzSaw

+1

Bạn có thể không có * có nghĩa là * để ngụ ý nó, nhưng bạn đã làm. – celtschk

2

Bộ nhớ trong vector đảm bảo sẽ được phân bổ liên tục kế nhau, và unsigned char là POD, do đó nó là hoàn toàn an toàn để memcpy vào nó (giả sử bạn không sao chép nhiều hơn bạn đã phân bổ, tất nhiên).

1

Có, giải pháp sử dụng memcpy là chính xác; bộ đệm được giữ bởi một vector là tiếp giáp. Nhưng nó không hoàn toàn an toàn, vì vậy hãy thích assign hoặc std::copy.

5

Có, nó là tốt để làm điều đó. Bạn có thể muốn làm myvet.data() thay vì &myvet[0] nếu có vẻ tốt hơn cho bạn, nhưng cả hai đều có cùng tác dụng.Ngoài ra, nếu hoàn cảnh cho phép, bạn có thể sử dụng std::copy để thay thế và có nhiều loại an toàn hơn và tất cả các tiện ích thư viện chuẩn khác của C++.

Bộ lưu trữ được sử dụng vector được đảm bảo tiếp giáp, làm cho nó phù hợp để sử dụng làm bộ đệm hoặc với các chức năng khác.

Hãy chắc chắn rằng bạn không thay đổi vector (chẳng hạn như gọi push_back vào nó, vv) trong khi bạn đang sử dụng con trỏ bạn nhận được từ data hoặc &v[0]vector có thể thay đổi kích thước bộ đệm của nó trên một trong những hoạt động và làm mất hiệu lực con trỏ.

3

Cách tiếp cận đó là chính xác, nó chỉ phụ thuộc vào vectơ có bộ nhớ tiếp giáp được yêu cầu theo tiêu chuẩn. Tôi tin rằng trong C++ 11 có một hàm thành viên data() mới trong vectơ trả về một con trỏ tới bộ đệm. Cũng lưu ý rằng trong trường hợp `memcpy bạn cần phải vượt qua kích thước bằng byte không phải là kích thước e của mảng

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