2009-03-22 8 views
77

Như (hy vọng) chúng ta đều biết, vector<bool> hoàn toàn bị hỏng và không thể được coi là mảng c. Cách tốt nhất để có được chức năng này là gì? Cho đến nay, những ý tưởng tôi đã nghĩ đến là:Cách thay thế cho vector <bool>

  • Sử dụng một vector<char> thay vào đó, hoặc
  • Sử dụng một lớp wrapper và có vector<bool_wrapper>

Làm thế nào để các bạn xử lý vấn đề này? Tôi cần hàm c_array().

Là một câu hỏi phụ, nếu tôi không cần phương thức c_array(), cách tốt nhất để tiếp cận vấn đề này là gì nếu tôi cần truy cập ngẫu nhiên? Tôi có nên sử dụng một deque hay cái gì khác?

Edit:

  • tôi làm cần kích thước động.
  • Đối với những người không biết, vector<bool> là chuyên môn để mỗi bool mất 1 bit. Vì vậy, bạn không thể chuyển đổi nó thành một mảng kiểu c.
  • Tôi đoán "trình bao bọc" là một chút nhầm lẫn. Tôi đã suy nghĩ một cái gì đó như thế này:

Tất nhiên, sau đó tôi phải đọc vào một my_bool do các vấn đề liên kết càng tốt :(

struct my_bool 
{ 
    bool the_bool; 
}; 
vector<my_bool> haha_i_tricked_you; 
+2

Có một số lý do để không sử dụng ... một mảng kiểu C? – kquinn

+0

rlbond, bạn có cần kích thước động không? –

+14

Ok tôi sẽ cắn - tại sao bạn nghĩ rằng vector là "" hoàn toàn bị hỏng "? –

Trả lời

35

Sử dụng std::deque nếu bạn không cần mảng, vâng .

Nếu không sử dụng một sự thay thế vector không chuyên trên bool, chẳng hạn như một trong Boost Container.

+1

Tại sao không sử dụng 'boost :: container :: vector' làm việc cho' bool' như mong đợi? – gnzlbg

+1

@gnzlbg - tốt gọi, tôi đã cập nhật câu trả lời (tôi đã đăng nó hơn hai năm trước khi Container được thêm vào Boost!) –

14

Phụ thuộc vào nhu cầu của bạn. tôi w hãy đi đến std::vector<unsigned char>. Viết một wrapper có thể được sử dụng tốt nếu bạn chỉ sử dụng một tập con của các chức năng, nếu không nó sẽ trở thành một cơn ác mộng.

20

Đó là một vấn đề thú vị.

Nếu bạn cần những gì sẽ là một std :: vector nếu nó không phải là chuyên ngành, thì có lẽ cái gì đó như thế sẽ làm việc tốt với trường hợp của bạn:

#include <vector> 
#include <iostream> 
#include <algorithm> 

class Bool 
{ 
public: 

    Bool(): m_value(){} 
    Bool(bool value) : m_value(value){} 

    operator bool() const { return m_value;} 

    // the following operators are to allow bool* b = &v[0]; (v is a vector here). 
    bool* operator&() { return &m_value; } 
const bool * const operator&() const { return &m_value; } 

private: 

    bool m_value; 

}; 




int main() 
{ 
    std::vector<Bool> working_solution(10, false); 


    working_solution[5] = true; 
    working_solution[7] = true; 


    for(int i = 0; i < working_solution.size(); ++i) 
    { 
     std::cout<< "Id " << i << " = " << working_solution[i] << "(" <<(working_solution[i] ? "true" : "false") << ")" <<std::endl; // i used ? : to be sure the boolean evaluation is correct 
    } 

    std::sort(working_solution.begin(), working_solution.end()); 
    std::cout<< "--- SORTED! ---" << std::endl; 

    for(int i = 0; i < working_solution.size(); ++i) 
    { 
      bool* b = &working_solution[i]; // this works! 

     std::cout<< "Id " << i << " = " << working_solution[i] << "(" << (working_solution[i] ? "true" : "false") << ")" <<std::endl; // i used ? : to be sure the boolean evaluation is correct 
    } 

    std::cin.get(); 
    return 0; 
} 

Tôi cố gắng này với VC9 và nó có vẻ làm việc tốt. Ý tưởng của lớp Bool là mô phỏng kiểu bool bằng cách cung cấp cùng một hành vi và kích thước (nhưng không cùng loại). Hầu như tất cả công việc được thực hiện bởi toán tử bool và các hàm tạo bản sao mặc định tại đây. Tôi đã thêm một loại để chắc chắn nó phản ứng như được giả định khi sử dụng các thuật toán.

Không chắc chắn nó sẽ phù hợp với tất cả các trường hợp. Nếu nó phù hợp với nhu cầu của bạn, nó sẽ ít hoạt động hơn là viết lại một lớp giống vectơ ...

+0

không giải pháp complette bạn không thể viết một cái gì đó như: bool * b = &v[0]; – bayda

+0

Đúng vậy, bạn chỉ có thể reinterpret_cast nó. – Klaim

+2

làm giải pháp chúng tôi có thể thêm toán tử bool * &() {return & m_value; } và chuyển đổi thành const bool *, thành bool & và const bool &. Nhưng dù sao - ý tưởng chính là chính xác. – bayda

4

vấn đề này đã được thảo luận trên comp.lang.C++.kiểm duyệt (http://groups.google.ru/group/comp.lang.c++.moderated/browse_thread/thread/b8d6dd59dfb295c0/e23e0f606d64550a)
giải pháp đề xuất:

  • cấp phát của riêng bạn (dựa trên std :: cấp phát) và chuyên môn hóa vector riêng;
  • sử dụng std :: deque (sớm được đề xuất trong một trong những cuốn sách S. Mayers) - nhưng điều này không cho yêu cầu của bạn;
  • làm cho trình bao bọc POD bool;
  • sử dụng thứ gì đó (char/int/etc) với cùng kích thước như bool thay vì bool;

cũng sớm tôi thấy đề xuất cho cam kết chuẩn - giới thiệu macro (giống như STD_VECTOR_BOOL_SPECIAL) cho phép không chuyên môn hóa này - nhưng không được triển khai trong triển khai STL và không được chấp thuận.

có vẻ như vấn đề của bạn không có cách để làm điều này độc đáo .. có lẽ trong C++ 0x

5

Xem xét sử dụng một vector < int>. Một khi bạn nhận được quá trình biên dịch và kiểm tra kiểu, bool và int là cả hai từ máy (chỉnh sửa: dường như điều này không phải lúc nào cũng đúng, nhưng sẽ đúng trên nhiều kiến ​​trúc PC). Trong những trường hợp mà bạn muốn chuyển đổi mà không có cảnh báo, hãy sử dụng "bool foo = !! bar", chuyển đổi số không thành false và không phải thành 0.

Một véc tơ < char> hoặc tương tự sẽ sử dụng ít không gian hơn, mặc dù nó cũng có khả năng đạt tốc độ (rất nhỏ) trong một số trường hợp vì ký tự ít hơn kích thước từ máy. Đây là, tôi tin rằng, lý do chính mà bools được thực hiện bằng cách sử dụng int thay vì ký tự.

Nếu bạn thực sự muốn ngữ nghĩa sạch, tôi cũng thích đề xuất tạo lớp boolean của riêng bạn - trông giống như một bool, hoạt động giống như một bool, nhưng ngu ngốc chuyên môn mẫu.

Ngoài ra, chào mừng bạn đến với câu lạc bộ của những người muốn vector < bool> chuyên môn giảm từ tiêu chuẩn C++ (với bit_vector để thay thế nó). Đó là nơi mà tất cả những đứa trẻ tuyệt vời đi chơi :).

+5

bool và int không nhất thiết phải là từ máy. Trên hệ thống tôi phát triển, sizeof (bool) = 1 và sizeof (int) = 4. Yêu cầu căn chỉnh và hướng dẫn tải/lưu trữ được tạo ra khác nhau tương ứng. – leander

10

Các bạn xử lý vấn đề này như thế nào? Tôi cần hàm c_array().

boost::container::vector<bool>:

vector < bool> chuyên môn đã được khá nhiều vấn đề, và đã có nhiều cố gắng không thành công không chấp hoặc loại bỏ nó khỏi tiêu chuẩn. Boost.Container không thực hiện nó vì có giải pháp tăng cường cao hơn Boost.DynamicBitset.

...

Vì vậy boost :: chứa :: vector :: iterator lợi nhuận bool thực tài liệu tham khảo và hoạt động như một container hoàn toàn tuân thủ. Nếu bạn cần phiên bản tối ưu hóa bộ nhớ của boost :: containers :: vector < bool> chức năng, vui lòng sử dụng Boost.DynamicBitset.

+0

Đây thực sự là giải pháp tốt nhất được đề xuất. – gnzlbg

3

Câu trả lời đơn giản nhất là sử dụng vector<struct sb> trong đó sbstruct {boolean b};. Sau đó, bạn có thể nói push_back({true}). Nó có vẻ tốt.