2012-06-26 25 views
22

Có cách nào an toàn và tiêu chuẩn phù hợp để xử lý một mảng kiểu C dưới dạng mảng std :: mà không sao chép dữ liệu vào mảng std :: mới không?Xử lý mảng c cstyle như std :: array

Điều này rõ ràng không biên dịch, nhưng là hiệu ứng tôi muốn (sử dụng thực sự của tôi phức tạp hơn nhưng mẫu ngắn này sẽ hiển thị những gì tôi muốn làm). Tôi đoán một reinterpret_cast sẽ "làm việc" nhưng có lẽ không an toàn?

#include <array> 

int main() 
{ 
    int data[] = {1, 2, 3, 4, 5}; 

    // This next line is the important one, treating an existing array as a std::array 
    std::array<int, 5>& a = data; 
} 

Dường như dữ liệu phải được lưu trữ giống hệt nhau.

chỉnh sửa: Để rõ ràng, tôi không muốn xóa mảng :: std mới, tôi muốn tham chiếu đến dữ liệu hiện có dưới dạng một.

+1

STL container quản lý bộ nhớ của riêng chúng. Bạn không thể tạo một mảng và có nó quản lý một số mảng mà bạn đã phân bổ ở nơi khác. – krammer

+2

Cho rằng 'std :: array' và' std :: vector' mong muốn quản lý bộ nhớ riêng của chúng, bạn nên cẩn thận khi sử dụng 'reinterpret_cast' mà không thực hiện các bước để đảm bảo chúng không thử và xóa dữ liệu dưới sự kiểm soát của họ. Nhưng điều đó sang một bên ... đừng sợ 'memcpy'. Một thói quen khá hiệu quả của nó, sau khi tất cả. – Rook

+0

Ok cảm ơn. Tôi muốn làm điều này một cách an toàn, không làm một hack, tôi chỉ tự hỏi nếu nó có thể là tất cả :) – jcoder

Trả lời

8

Bạn không thể làm điều đó. std::array là tổng hợp và chứa khối dữ liệu của riêng nó (trái ngược với một con trỏ tới một khối dữ liệu có thể dễ dàng được gán lại). Vì vậy, không có cách nào để tránh một bản sao của tất cả các yếu tố. Trong C++ 11, điều này đặc biệt quan trọng vì dữ liệu của mảng không thể di chuyển được, vì vậy không có hàm std::swap hiệu quả.

+5

Tôi hiểu điều đó. Tôi không muốn tạo một mảng std :: mới với dữ liệu riêng của nó, tôi muốn tham chiếu đến dữ liệu hiện có như thể nó là một mảng std :: vì chúng có khả năng là cùng một bố cục. Nếu nó có thể làm một cách an toàn đó là. Tôi chắc chắn một reinterpret_cast "hack" sẽ "làm việc" ... – jcoder

+0

upvoted anyway là "xin lỗi bạn không thể làm điều đó một cách an toàn" là một câu trả lời tốt cho câu hỏi ngay cả khi không phải là những gì tôi hy vọng. – jcoder

7

Bạn có thể sử dụng reinterpret_cast, tuy nhiên lưu ý rằng nó là một bẩn hack xấu xí và bạn không nên làm điều gì đó như thế này trong mã phát hành thực sự của bạn:

std::array<int, 5> &a = reinterpret_cast<std::array<int, 5>&>(data); 

Những vấn đề có thể phát sinh nếu việc thực hiện nội bộ của std :: mảng thay đổi (ví dụ: một số trường bổ sung sẽ được thêm vào trong phiên bản gỡ lỗi của STL để thực hiện một số kiểm tra thời gian chạy). Sau đó, mã này sẽ bắt đầu gặp sự cố mà không có bất kỳ thông báo nào (vì nó dựa trên giả thiết ngầm rằng std :: đối tượng mảng và mảng C có cùng bố cục bộ nhớ).

Nếu bạn quyết định đi cho bẩn hack xấu xí dù sao, ít nhất là thêm một tấm séc kích thước thời gian biên dịch:

C_ASSERT(sizeof(a) == sizeof(data)); 

Điều này sẽ tạo ra một lỗi trong trường hợp kích thước của std :: mảng <> điểm dừng phù hợp với kích thước của mảng C của bạn (do một số thay đổi trong việc thực hiện STL).

+0

Vâng, tôi có điều này để "làm việc". Tôi chỉ tự hỏi nếu có một cách mà không phải là một hack bẩn xấu xí :) cảm ơn – jcoder

+3

Tên 'reinterpret_cast' là cố ý xấu xí để làm cho rõ ràng rằng một hack xấu xí đang được sử dụng. – MSalters

+0

Cảm ơn, câu trả lời hay. Tôi sẽ không đi với một hack bẩn. Chỉ có một trường hợp trong mã của tôi, nơi tôi đã có một mảng có kích thước cố định vì vậy muốn sử dụng std :: mảng trong suốt mã của tôi, nhưng mã cũ mà tôi không thể thay đổi đã cho tôi một mảng kiểu c. Tôi sẽ không làm một hack cho nó, nhưng nó sẽ được tốt đẹp để có thể làm một cái gì đó hiệu quả và hỗ trợ. – jcoder

15

Như đã thảo luận trong bài viết này Is std::array<T, S> guaranteed to be POD if T is POD?

std::array<int, N> là POD và bố trí như vậy, tiêu chuẩn. Theo như tôi hiểu các yêu cầu bố trí tiêu chuẩn, điều này có nghĩa là con trỏ đến đối tượng giống hệt với con trỏ đến thành viên đầu tiên. Kể từ std :: mảng không có thành viên riêng tư/được bảo vệ (theo http://en.cppreference.com/w/cpp/container/array), điều này nên đồng ý với phần tử đầu tiên trong mảng được bao bọc. Như vậy một cái gì đó giống như

reinterpret_cast< std::array<int, 5>* >(&data)

là theo ý kiến ​​của tôi được bảo đảm để làm việc theo tiêu chuẩn. Tuy nhiên, tôi phải thừa nhận rằng đôi khi tôi gặp khó khăn khi giải thích ngôn ngữ chuẩn, vì vậy hãy sửa tôi nếu tôi sai.

Kính trọng Claas

+2

Tôi nghĩ bạn đúng nhưng tôi sẽ kiểm tra xem array5 * p = reinterpret_cast < array5* > (& dữ liệu); ASSERT (p-> data() == &data); đó là những gì chúng tôi muốn – GameDeveloper

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