2

当我遍历 avector<bool>时,我发现通过迭代器取消引用的元素被识别为就好像它们是 const 一样。这是为什么?更改容器或元素类型,例如list<bool>or 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>,此程序将“const”打印到控制台。将顶部的 typedef 和 manifest 常量更改为除了这两个组合之外的任何内容,它会打印“非常量”。此外,如果我将 , 行替换为iss >> *itT v; iss >> v; *it = v;它会按预期工作——所有组合都会打印“非常量”。

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

4

3 回答 3

6

尽管有名字,但vector<bool>不包含bools,并且取消引用它的迭代器不会给你一个bool&. 相反,它为您提供了一个 type 的对象vector<bool>::reference,它试图尽可能bool&多地模仿 的行为。

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

于 2015-06-21T00:13:21.423 回答
5

为了节省内存,vector<bool>它不是一个实际的bool. 一个 bool 值只需要存储一个位,但可能的最小大小是 1byte = 8bits。因此,通过不使用简单的实现,您可以获得比简单的 bool 数组提供的存储效率高 8 倍的存储(就内存而言)。

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

你仍然可以将它转换为 a bool,或者用它初始化一个新const bool对象......然后用这个新对象做任何你想做的事情

于 2015-06-21T00:17:48.287 回答
2

std::vector<bool>是一种特殊化,std::vector它充当节省空间的动态位集。迭代器返回begin()end()实际指向代表布尔值的代理类类型的对象。

从取消引用迭代器返回的引用是类类型的纯右值,而不是实际的布尔值。它被转换为bool类型的纯右值,这就是为什么需要引用 const 的重载(右值可以绑定到对 const 的引用)。

于 2015-06-21T00:13:46.993 回答