为什么非const vector <bool>元素是const?

时间:2015-06-20 23:58:46

标签: c++ vector boolean const extraction-operator

当我遍历vector<bool>时,我发现通过迭代器解除引用的元素被识别为它们是const。这是为什么?更改容器或元素类型,例如list<bool>vector<short>,元素是非常量的。此代码显示了我正在谈论的内容:

typedef bool T;
#define C vector
istringstream &operator>>(istringstream &iss, T &v)
{
    cout << "non-const" << endl;
    return iss;
}

istringstream &operator>>(istringstream &iss, const T &v)
{
    cout << "const" << endl;
    return iss;
}

istringstream &operator>>(istringstream &iss, C<T> &c)
{
    for (C<T>::iterator it = c.begin(); it != c.end(); ++it)
    {
        iss >> *it;
    }
    return iss;
}

int main()
{
    C<T> c(1);
    istringstream iss("1");
    iss >> c;
}

对于vector<bool>,此程序打印&#34; const&#34;到控制台。将顶部的typedef和manifest常量更改为除了这两个组合之外的任何内容,并打印&#34; non-const。&#34;另外,如果我用iss >> *it替换行T v; iss >> v; *it = v;,它会按预期工作 - 所有组合打印&#34;非常数。&#34;

我在GCC 4.1.2 C ++ 98(通过codepad.org)和VS2015 C ++ 14 +(?)中看到了相同的行为。

3 个答案:

答案 0 :(得分:6)

尽管有名称,vector<bool>不包含bool,但解除引用它的迭代器并没有给你bool&。相反,它会为您提供类型为vector<bool>::reference的对象,该对象会尝试尽可能多地模仿bool&的行为。

无法将vector<bool>::reference转换为bool&,因此非常量超载不起作用。但是,vector<bool>::reference可以转换为bool,然后可以绑定到const bool&

答案 1 :(得分:5)

为节省内存,vector<bool>不是bool的实际数组。 bool值只需要存储一点,但可能的最小尺寸是1byte = 8bits。因此,通过不使用简单的实现,您可以将存储效率提高8倍(就内存而言),然后是一个简单的bool数组。

然而,结果是vector<bool>的元素不是bool而是vector<bool>::reference,它与bool&几乎但不完全相同。大多数操作都在这里,但有些不是(例如|=

您仍然可以将其转换为bool,或者使用它初始化新的const bool对象...并使用此新对象执行任何操作

答案 2 :(得分:2)

std::vector<bool>std::vector的特化,它可以充当空间效率的动态bitset。从begin()end()返回的迭代器实际上指向代表布尔值的代理类类型的对象。

从解除引用迭代器返回的引用是类类型的prvalues,而不是实际的布尔值。它被转换为bool类型的prvalue,这就是为什么引用了对const的引用的重载(rvalues可以绑定到const的引用)。