C++對vector bool::data()用memset報錯

本來想嘗試用 menset 來代替 forvector<bool> 賦初值,看會不會提速,報錯。出錯例程:

#include <cstdio>
#include <vector>
using namespace std;

int main()
{
	vector<bool> vb;
	vb.reserve(128);
	printf("vector<bool> ptr: %p\n", vb.data());  // ERROR
	return 0;
}

報錯:

err.cpp: In function 'int main()':
err.cpp:9:44: error: invalid use of void expression
  printf("vector<bool> ptr: %p\n", vb.data());

才知道 vector<bool> 是比較特殊的,用位存,而不是 bool 數組,不能照套 vector<int> 的 API。因爲 bitset 不能運行時指定長度,自己寫一個 bitset,順便測試一下性能,跟 vector<bool> 對比:

#include <bits/stdc++.h>
using namespace std;
const int N = 20000000;


struct bool_vec
{
	typedef unsigned int dtype;
	const int UNIT = sizeof(dtype),
			  B = 8 * UNIT,
			  MASK = (1LL << B) - 1;
	vector<dtype> vec;
	bool_vec(int size)
	{
		vec.reserve((size + B - 1) / B);
		// printf("B: %d, MASK: %x\n", B, MASK);
		// printf("wanted size: %d, capacity: %d\n", (size + B - 1) / B, vec.capacity());
	}
	inline int operator [] (int pos)
	{
		// return (vec[pos / B] >> (pos % B)) & 1;
		return (vec[pos / B] >> (pos & MASK)) & 1;
	}
	void set(int pos = -1)
	{
		if (pos >= 0)
		{
			// vec[pos / B] |= 1 << (pos % B);
			vec[pos / B] |= 1 << (pos & MASK);
		}
		else
			memset(vec.data(), 0xff, vec.capacity() * UNIT);
	}
	void reset(int pos = -1)
	{
		if (pos >= 0)
		{
			// vec[pos / B] &= ~(1 << (pos % B));
			vec[pos / B] &= ~(1 << (pos & MASK));
		}
		else
			memset(vec.data(), 0, vec.capacity() * UNIT);
	}
};


int main()
{
	vector<int> vi;
	vector<bool> vb;
	bool_vec b_vec(N);
	double cost;

	vi.reserve(N);
	vb.reserve(N);

	// for int
	clock_t start = clock();
	for (int *b = vi.data(), *e = vi.data() + N; b < e; )
		*b++ = -1;
	cost = (double)(clock() - start) / CLOCKS_PER_SEC;
	printf("for vector<int>: %f\n", cost);

	// memset int
	start = clock();
	memset(vi.data(), -1, N * sizeof(int));
	cost = (double)(clock() - start) / CLOCKS_PER_SEC;
	printf("memset vector<int>::data: %f\n", cost);

	// for bool
	start = clock();
	for (int i = 0; i < N; )
		vb[i++] = false;
	cost = (double)(clock() - start) / CLOCKS_PER_SEC;
	printf("for vector<bool>: %f\n", cost);
	
	// for bool_vec
	start = clock();
	for (int i = 0; i < N; )
		b_vec.set(i++); // set 1
	cost = (double)(clock() - start) / CLOCKS_PER_SEC;
	printf("for bool_vec: %f\n", cost);

	puts("--- test 1 ---");
	for (int i = 0; i < 200; i += 37)
		printf("b_vec[%d]: %d\n", i, b_vec[i]);

	// memset int
	start = clock();
	b_vec.reset();  // set 0
	// for (int i = 0; i < N; )
		// b_vec.reset(i++); // set 0
	printf("memset bool_vec: %f\n", cost);

	puts("--- test 0 ---");
	for (int i = 0; i < 200; i += 37)
		printf("b_vec[%d]: %d\n", i, b_vec[i]);

	return 0;
}

結果:

for vector<int>: 0.093191
memset vector<int>::data: 0.007326
for vector<bool>: 0.424405
for bool_vec: 0.136087
--- test 1 ---
b_vec[0]: 1
b_vec[37]: 1
b_vec[74]: 1
b_vec[111]: 1
b_vec[148]: 1
b_vec[185]: 1
memset bool_vec: 0.136087
--- test 0 ---
b_vec[0]: 0
b_vec[37]: 0
b_vec[74]: 0
b_vec[111]: 0
b_vec[148]: 0
b_vec[185]: 0

似乎比 vector<bool> 要快些少,然而比 memset vector<int> 要慢?這是爲什麼?函數也是調的 memset 啊

References

  1. What happens when you call data() on a std::vector?
  2. c++中爲什麼不提倡使用vector?
  3. Fast std::vector Reset
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章