我使用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);
}
}
Run Code Online (Sandbox Code Playgroud)
似乎size()调用正在访问未初始化的内存,对于长度为3或更长的向量,而不是大小为2的向量.Valgrind确认内存最近没有堆栈,malloc'd或free'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
}
Run Code Online (Sandbox Code Playgroud)
我没有对默认副本和移动构造函数做任何事情.
发生了什么,为什么我的测试失败了?
正如dyb所说,vector<xor_func> arr{3, temp};被解释为
vector<xor_func> arr({xor_func{3}, temp}),因为它可以隐式地由构造函数3转换为a xor_func,然后它可以选择要调用的构造函数的初始化列表版本.
如果你看一下Is C++ 11 Uniform Initialization是旧式语法的替代品吗?,你可以看到统一初始化语法的缺点之一就是这个bug.一个更微不足道的例子是
// std::string constructor prototype for reference
// fill (6)
string (size_t n, char c);
void main() {
string myString{65, 'B'};
cout << myString << endl;
}
Run Code Online (Sandbox Code Playgroud)
这将打印出"AB",而不是"BBBBBB ... BBB",因为它可以将65转换为'A',然后它就像我们写的那样myString{'A', 'B'}.要修复它,只需不要尝试为此调用使用统一初始化语法并将其替换为
string myString(65, 'B');
Run Code Online (Sandbox Code Playgroud)
我可以解决这个错误的另一种方法是将构造函数更改xor_func(const size_t size)为explicit xor_func(const size_t size),这可以防止编译器隐式转换3为xor_func.
哦,还有另一个很好的答案显式关键字在C++中意味着什么.
| 归档时间: |
|
| 查看次数: |
167 次 |
| 最近记录: |