2016-08-19 51 views
3

为什么下面的代码对于bool的std :: vector不起作用(如同被忽略)? 某些元素在bool向量中是随机错误的。 对于int向量都可以正常工作(用多于3个循环测试)。C++ OpenMP和std :: vector <bool>

我在ubuntu 14.04 64位g ++ 4.8.4。

#include <iostream> 
#include <vector> 

using namespace std; 


class TestBool 
{ 
public: 
    TestBool() {} 
    bool test() {return true;} 
    int testInt() {return 10;} 
}; 
void testBVec(vector<bool> &bv, size_t loop) 
{ 
    cout << "boolvec loop " << loop << endl; 
    for(size_t i = 0; i < bv.size(); i++) { 
     if(! bv[i]) 
      cout << "wholy shit with bool at index " << i << endl; 
    } 
} 
void testIntVec(vector<int> &iv, size_t loop) 
{ 
    cout << "intVec loop " << loop << endl; 
    for(size_t i = 0; i < iv.size(); i++) { 
     if(iv[i] != 10) 
      cout << "wholy shit with int at index " << i << endl; 
    } 
} 


int main() 
{ 
    vector<TestBool> tv(10); 
    size_t loops = 3; 

    for(size_t i = 0; i < loops; i++) { 
     vector<bool> bv(10); 
     vector<int> iv(10); 

     #pragma omp parallel for 
     for(int j = 0; j < 10; ++j) { 
      bv[j] = tv[j].test(); 
      iv[j] = tv[j].testInt(); 
     } 
     testBVec(bv, i+1); 
     testIntVec(iv, i+1); 
    } 

    return 0; 
} 
+2

https://isocpp.org/blog/2012/11/on-vectorbool – Mansuro

+0

感谢您的链接。 –

回答

5

很可能是因为vector<bool>被编译器转换为位数组。只要使用vector<int>vector<char>就可以存储0和1,如果你不需要位数组。

+0

也谢谢你,不知道。 –

6

vector<bool>是显式模板专门化,它将布尔值打包成一些整数变量的位。为了使这些位能够通过语义正确的下标进行写入,vector<bool>::operator[]返回一些proxy object,其可转换为bool并且具有布尔的赋值运算符。不同索引的代理对象可能会引用相同的底层内存,因此不能保证同时访问不同的位是线程安全的。

对于一个称职的证明,它不是一个编译器错误,see'Data种族this页的部分:

不同的元素同时访问是不能保证是线程安全的(如存储字节可以由多个位共享)。

或第23.2.2 the C++ Standard的:

  • < ...>实现都必须避免数据争用时所包含的对象的在不同的内容除了vector<bool>之外,相同序列中的元素被同时修改。
  • < ...>作为一般规则的例外,对于vector<bool> y,y[0] = true可以与y[1] = true竞赛。
  • 作为@Anton建议,使用比bool之外的类型。

    1

    除了Sergey和Anton的回答,让我指出该向量已知不是线程安全的,如http://www.cplusplus.com/reference/vector/vector-bool中的数据竞赛部分所述。

    你的替代品(如其他建议),要么去其他类型的载体或保护的声明

    bv[j] = tv[j].test(); 
    

    #pragma omp critical

    相关问题