2013-02-06 39 views
12

Tôi không thể tìm thấy câu hỏi đó và đó là vấn đề thực tế mà tôi đang gặp phải.Làm thế nào để chuyển đổi std :: vector <unsigned char> thành vector <char> mà không cần sao chép?

Tôi có tiện ích tải tệp trả về std::vector<unsigned char> chứa toàn bộ nội dung tệp. Tuy nhiên, chức năng xử lý yêu cầu mảng contiguos là char (và không thể thay đổi - đó là chức năng thư viện). Vì lớp đang sử dụng hàm xử lý lưu trữ một bản sao của dữ liệu, tôi muốn lưu trữ nó như là vector<char>. Đây là mã có thể minh họa hơn một chút.

std::vector<unsigned char> LoadFile (std::string const& path); 

class Processor { 
    std::vector<char> cache; 
    void _dataOperation(std::vector<char> const& data); 

public: 
    void Process() { 
     if (cache.empty()) 
      // here's the problem! 
      cache = LoadFile("file.txt"); 

     _dataOperation(cache); 
    } 
}; 

Mã này không biên dịch, vì (rõ ràng) không có chuyển đổi phù hợp. Tuy nhiên, chúng tôi có thể chắc chắn rằng vectơ tạm thời sẽ có cùng một lượng bộ nhớ (IOW sizeof(char) == sizeof(unsigned char))

Giải pháp ngây thơ sẽ lặp lại nội dung tạm thời và truyền mọi ký tự. Tôi biết rằng trong trường hợp bình thường, operator= (T&&) sẽ được gọi.

Trong trường hợp của tôi, việc chuyển đổi lại thông tin trở nên an toàn, vì tôi chắc chắn tôi sẽ chỉ đọc các ký tự ASCII. Bất kỳ ký tự nào khác cũng sẽ bị bắt trong _dataOperation.

Vì vậy, câu hỏi của tôi là: cách chuyển đổi vector tạm thời đúng cách và an toàn theo cách không liên quan đến việc sao chép?

Nếu không thể, tôi thích cách sao chép an toàn hơn là không an toàn. Tôi cũng có thể thay đổi LoadFile để trả lại vector<char> hoặc vector<unsigned char>.

+1

Nếu bạn kiểm soát mã của '_dataOperation', có thể bạn sẽ hạnh phúc hơn về lâu dài nếu bạn làm cho nó lấy' vector '. – zwol

+0

@Zack thật không may, tôi không. Đó là một chức năng thư viện. Tôi sẽ chỉnh sửa câu hỏi. –

+0

Không có _safe_ way –

Trả lời

6

Trong C++ 11, [basic.lval] p10 nói,

Nếu một chương trình cố gắng truy cập vào các giá trị được lưu trữ của một đối tượng thông qua một glvalue của khác hơn là một trong các loại sau đây hành vi này là undefined:

  • ...
  • loại char hoặc unsigned char.

(vị trí chính xác có thể khác nhau trong các phiên bản khác của C++, nhưng ý nghĩa là như nhau.)

Điều đó có nghĩa rằng bạn có thể mất một vector<unsigned char> cache và truy cập vào nội dung của nó bằng cách sử dụng phạm vi [reinterpret_cast<char*>(cache.data()), reinterpret_cast<char*>(cache.data()) + cache.size()). (@Kerrek SB đề cập này.)

Nếu bạn lưu trữ một vector<unsigned char> trong Processor để phù hợp với kiểu trả về của LoadFile, và _dataOperation() thực sự mất một mảng của char (có nghĩa là a và một kích thước const char*), sau đó bạn có thể cast khi bạn đang đi qua các lập luận để _dataOperation()

Tuy nhiên, nếu _dataOperation() mất một vector<char> đặc biệt và bạn lưu trữ một vector<unsigned char> cache, sau đó bạn không thể vượt qua nó reinterpret_cast<vector<char>&>(cache). (tức là @ André Puel là hoàn toàn sai. Đừng nghe anh ta.) Điều đó vi phạm các quy tắc bí danh, và trình biên dịch sẽ cố gắng làm tức giận khách hàng của bạn lúc 2 giờ sáng.(Và nếu phiên bản này của trình biên dịch của bạn không quản lý nó, phiên bản tiếp theo sẽ tiếp tục cố gắng.)

Một tùy chọn là, như bạn đã đề cập đến mẫu LoadFile() và trả lại (hoặc điền vào) một vectơ của loại bạn muốn. Một cách khác là sao chép kết quả, trong đó phiên bản ngắn gọn lại là reinterpret_cast của vector nguồn .data(). [basic.fundamental] p1 đề cập rằng "Đối với các kiểu ký tự, tất cả các bit của biểu diễn đối tượng tham gia vào biểu diễn giá trị.", có nghĩa là bạn sẽ không mất dữ liệu với số reinterpret_cast. Tôi không thấy bảo đảm chắc chắn rằng không có mẫu bit nào của unsigned char có thể gây ra bẫy nếu reinterpret_cast'ed đến char, nhưng tôi không biết bất kỳ phần cứng hoặc trình biên dịch hiện đại nào làm điều đó.

+0

Cảm ơn bạn đã trả lời đầy đủ. –

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