尝试更改向量 bool 中的值

发布于 2025-01-13 02:04:58 字数 983 浏览 2 评论 0原文

我正在阅读 Stroustrup PPP 并在做练习时发现了这个错误。

为什么我无法更改矢量布尔值?

#include "std_lib_facilities.h"

int main()
{
  vector<bool> vecc(2, true);

  vecc[1] = true; // I can't do this, returns error.

  return 0;
}

错误:

错误:无法绑定“bool&”类型的非常量左值引用to an rvalue of type 'bool' return std::vector::operator[](i);

其次,当我尝试使用 int 类型时,问题不会发生。

#include "std_lib_facilities.h"

int main(){
  vector<int> vecc = {true, true};


  for(bool x : vecc) {cout<<x<<"\n";}

  vecc[1] = false; //ok

  for(bool x : vecc){cout<<x<<"\n";}
  return 0;
}

输出:

1
1
1
0

编辑:

可能这是因为我正在使用 #include "std_lib_facilities.h"

std_lib_facilities.h

I'm reading Stroustrup PPP and while doing an exercise, I found this error.

Why I can't change the value of a vector bool?

#include "std_lib_facilities.h"

int main()
{
  vector<bool> vecc(2, true);

  vecc[1] = true; // I can't do this, returns error.

  return 0;
}

The error:

error: cannot bind non-const lvalue reference of type 'bool&' to an rvalue of type 'bool' return std::vector<T>::operator[](i);

Second, when I try with the int type, the problem does not occur.

#include "std_lib_facilities.h"

int main(){
  vector<int> vecc = {true, true};


  for(bool x : vecc) {cout<<x<<"\n";}

  vecc[1] = false; //ok

  for(bool x : vecc){cout<<x<<"\n";}
  return 0;
}

Output:

1
1
1
0

Edit:

Probably this is because I was using #include "std_lib_facilities.h"

std_lib_facilities.h

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

清风不识月 2025-01-20 02:04:58

以添加一些错误检查功能,以帮助人们开始其编程生涯:

// trivially range-checked vector (no iterator checking):
template< class T> struct Vector : public std::vector<T> {
    using size_type = typename std::vector<T>::size_type;

/* #ifdef _MSC_VER
    // microsoft doesn't yet support C++11 inheriting constructors
    Vector() { }
    explicit Vector(size_type n) :std::vector<T>(n) {}
    Vector(size_type n, const T& v) :std::vector<T>(n, v) {}
    template <class I>
    Vector(I first, I last) : std::vector<T>(first, last) {}
    Vector(initializer_list<T> list) : std::vector<T>(list) {}
*/
    using std::vector<T>::vector;   // inheriting constructor

    T& operator[](unsigned int i) // rather than return at(i);
    {
        if (i<0 || this->size() <= i) throw Range_error(i);
        return std::vector<T>::operator[](i);
    }
    const T& operator[](unsigned int i) const
    {
        if (i<0 || this->size() <= i) throw Range_error(i);
        return std::vector<T>::operator[](i);
    }
};

std_lib_facilities.h 定义了以下帮助程序模板, operator[](unsigned int i) 及其 const 变体返回对 T 的引用,在本例中 T布尔。为了获取它调用 std::vectoroperator[] 的元素来完成繁重的工作。

不幸的是 std::vector 不是一个合适的库容器。由于它打包位而不是存储 bool,因此它无法从元素访问方法返回对 bool 的引用。它没有任何可供引用的 bool相反,它返回一个隐藏了收拾行李远离视线,通常会让生活变得更轻松一些。在大多数情况下,元素访问方法的行为与常规向量完全相同。

但这次不是。它不返回引用,也不返回对 bool 的引用,因此简单的传递无法编译。

常见的解决方法是使用包含一些小整数类型或 enumstd::vector 或使用 std::deque其使用方式大致相同,并且没有位支持专门化。如果大小在编译时已知,请考虑使用 std::bitset< /代码>

std_lib_facilities.h defines the following helper template to add a bit of error checking helpful to folks beginning their programming careers:

// trivially range-checked vector (no iterator checking):
template< class T> struct Vector : public std::vector<T> {
    using size_type = typename std::vector<T>::size_type;

/* #ifdef _MSC_VER
    // microsoft doesn't yet support C++11 inheriting constructors
    Vector() { }
    explicit Vector(size_type n) :std::vector<T>(n) {}
    Vector(size_type n, const T& v) :std::vector<T>(n, v) {}
    template <class I>
    Vector(I first, I last) : std::vector<T>(first, last) {}
    Vector(initializer_list<T> list) : std::vector<T>(list) {}
*/
    using std::vector<T>::vector;   // inheriting constructor

    T& operator[](unsigned int i) // rather than return at(i);
    {
        if (i<0 || this->size() <= i) throw Range_error(i);
        return std::vector<T>::operator[](i);
    }
    const T& operator[](unsigned int i) const
    {
        if (i<0 || this->size() <= i) throw Range_error(i);
        return std::vector<T>::operator[](i);
    }
};

T& operator[](unsigned int i) and its const variant return a reference to T and in this case T is bool. To get the element it calls through to std::vector's operator[] to do the grunt work.

Unfortunately std::vector<bool> is not a proper library container. Because it packs bits rather than storing bools, it can't return a reference to a bool from the element access methods. It doesn't have any bools to reference. Instead it returns a groovy reference class that conceals the bit packing from sight and usually makes life a bit easier. Under most circumstances the element access methods will behave exactly the same way as a regular vector.

But not this time. It's not returning a reference and it's not returning a reference to a bool so the simple pass-through fails to compile.

Common work arounds are to use a std::vector containing some small integer type or an enum or use a std::deque<bool> which can be used largely the same way and doesn't have a bit-backing specialization. If the size is known at compile time, consider using a std::bitset.

濫情▎り 2025-01-20 02:04:58

标准库为 bool 类型提供了 std::vector 的专门化,这可以针对空间效率进行优化。这会将 bool 存储为 1 位,为大型向量节省大量内存。

问题是您无法返回对位的引用,因此标准库应该返回允许分配的位周围的引用对象包装器。该对象保留对向量和您要求的位位置的引用,并有一个调用 std::vector::assign()operator=()

示例代码甚至是这样的:

std::vector<bool> is_prime(N, true);
is_prime[0] = is_prime[1] = false;

我唯一能想到的是你的编译器有一个旧版本的 STL 或一个糟糕的实现,它确实有向量专门化但没有包装器引用对象。尝试

vecc.assign(1, true);

The standard library provides a specialization of std::vector for the type bool, which may be optimized for space efficiency. This stores bool as 1 bit saving you a lot of memory for large vectors.

The problem with that is that you can not return a reference to a bit so the standard library is supposed to return reference object wrapper around the bit that allows assignment. The object keeps a reference to the vector and the bit position you asked for and has an operator=() that calls std::vector<bool>::assign().

The example code for this even has this:

std::vector<bool> is_prime(N, true);
is_prime[0] = is_prime[1] = false;

Only thing I can think of is that your compiler has an old version of the STL or a bad implementation that does have a vector specialization but without the wrapper reference object. Try

vecc.assign(1, true);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文