【问题标题】:Why are non-const vector<bool> elements const?为什么非 const vector<bool> 元素是 const 的?
【发布时间】:2015-06-20 23:58:46
【问题描述】:

当我迭代 vector&lt;bool&gt; 时,我发现通过迭代器取消引用的元素被识别为 const。这是为什么?更改容器或元素类型,例如list&lt;bool&gt;vector&lt;short&gt;,并且元素是非常量的。这段代码显示了我在说什么:

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&lt;bool&gt;,此程序将“const”打印到控制台。将顶部的 typedef 和 manifest 常量更改为除了这两个组合之外的任何内容,它会打印“非常量”。此外,如果我将行 iss &gt;&gt; *it 替换为 T v; iss &gt;&gt; v; *it = v;,它将按预期工作——所有组合都打印“非常量”。

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

【问题讨论】:

  • 简答:std::vector&lt;bool&gt; 很特别。你可以在上面找到参考,看看有什么不同。
  • 是的,我,呃,刚刚注意到了。我正在写一些花哨的模板,我宁愿不专攻 bool。
  • vector&lt;bool&gt; 上阅读一些有趣的事实:isocpp.org/blog/2012/11/on-vectorbool
  • 简短版:vector&lt;bool&gt; 不是容器。

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


【解决方案1】:

尽管有名字,vector&lt;bool&gt; 不包含bools,并且取消引用它的迭代器不会给你一个bool&amp;。相反,它为您提供了一个vector&lt;bool&gt;::reference 类型的对象,它会尽可能地模仿bool&amp; 的行为。

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

【讨论】:

    【解决方案2】:

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

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

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

    【讨论】:

      【解决方案3】:

      std::vector&lt;bool&gt;std::vector 的特化,它充当节省空间的动态位集。从begin()end() 返回的迭代器实际上指向代表布尔值的代理类类型的对象。

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

      【讨论】:

      • 感谢 chris、T.C. 和 0x499602D2。这就解释了。听从克里斯的建议,我找到了good article
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-06-02
      • 2013-04-24
      • 1970-01-01
      • 2016-11-11
      • 2011-06-03
      • 2015-09-07
      • 2019-03-05
      相关资源
      最近更新 更多