为什么以下代码对bool的std :: vector不起作用(如所考虑的)? bool-vector中的一些元素是随机错误的。 对于int向量,所有工作正常(使用多于3个循环进行测试)。
我在ubuntu 14.04 64bit上使用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;
}
答案 0 :(得分:6)
vector<bool>
是显式模板特化,它将布尔值打包成一些整数变量的位。为了通过语义正确的下标使位可写,vector<bool>::operator[]
返回一些proxy object,它可转换为bool
并具有bool的赋值运算符。不同索引的代理对象可以引用相同的底层内存,因此不能保证对不同位的同时访问是线程安全的。
如果有合格证明它不是编译器错误,请参阅this页面的“数据竞赛”部分:
不保证同时访问不同的元素是线程安全的(因为存储字节可能由多个位共享)。
或the C++ Standard的第23.2.2节:
- &LT; ...&GT;当同一序列中不同元素中包含的对象的内容(
vector<bool>
除外)同时修改时,需要实现以避免数据争用。- &LT; ...&GT;作为一般规则的例外,对于
醇>vector<bool> y
,y[0] = true
可能会与y[1] = true
竞赛。
正如@Anton建议的那样,使用bool
以外的类型。
答案 1 :(得分:5)
很可能是因为vector<bool>
被编译器转换为位数组。如果您不需要位数组,只需使用存储0和1的vector<int>
或vector<char>
。
答案 2 :(得分:1)
除了Sergey和Anton的答案之外,我还要指出,已知向量不是线程安全的,如http://www.cplusplus.com/reference/vector/vector-bool中的数据竞争部分所述。
您的替代方案(正如其他人建议的那样)要么转到其他类型的向量,要么保护声明
bv[j] = tv[j].test();
#pragma omp critical
。