我使用vector的length和value构造函数创建了一个名为xor_funcs的bitpacked向量的向量。 这是失败的测试:
TEST(vectorInit, size3) {
const xor_func temp{false, {0,0,0}};
vector<xor_func> arr{3, temp};
for(xor_func& f : arr) {
EXPECT_EQ(3, f.size()) << f;
}
for(int i = 0; i < 3; i++) {
ASSERT_EQ(3, arr[i].size()) << "for i=" << i;
arr[i].set(i);
}
}
似乎size()
调用正在访问未初始化的内存,对于长度为3或更长的向量,而不是大小为2的向量.Valgrind确认内存最近不是堆栈&#39; d,malloc&#39 ; d或免费&#39; d。
xor_func
定义如下:
class xor_func {
private:
boost::dynamic_bitset<> bitset;
bool negated;
public:
xor_func(const bool neg, const std::initializer_list<int> lst);
// That's defined in cpp
xor_func(const size_t size) : bitset(size), negated(false) {}
// Disallow the trivial constructor, since I don't want
// any 0 length xor_funcs existing by default.
// xor_func() : bitset(), negated(false) {}
xor_func(const bool negated, const boost::dynamic_bitset<> bitset)
: bitset(bitset), negated(negated) {}
// That's all the constructors.
// Snip
}
我没有对默认副本和移动构造函数做任何事情。
发生了什么,为什么我的测试失败了?
答案 0 :(得分:5)
正如dyb所说,vector<xor_func> arr{3, temp};
被解释为
vector<xor_func> arr({xor_func{3}, temp})
,因为3
可以隐式地由构造函数转换为xor_func
,然后它可以选择要调用的构造函数的初始化列表版本。
如果你看一下Is C++11 Uniform Initialization a replacement for the old style syntax?,你会发现统一初始化语法的一个缺点就是这个bug。一个更简单的例子是
// std::string constructor prototype for reference
// fill (6)
string (size_t n, char c);
void main() {
string myString{65, 'B'};
cout << myString << endl;
}
这将打印出“AB”,而不是“BBBBBB ... BBB”,因为它可以将65转换为'A',然后就好像我们写了myString{'A', 'B'}
一样。要解决此问题,请不要尝试为此调用使用统一初始化语法,并将其替换为
string myString(65, 'B');
我可以修复此错误的另一种方法是将构造函数xor_func(const size_t size)
更改为explicit xor_func(const size_t size)
,这会阻止编译器将3
隐式转换为xor_func
。< / p>
哦,还有另一个很好的答案What does the explicit keyword mean in C++。