【发布时间】:2013-03-25 14:31:32
【问题描述】:
我有这个代码:
#include <iostream>
#include <vector>
using namespace std;
int main(){
vector <bool> v;
cin >> v[0];
return 0;
}
为什么我不能这样做?编译器不会编译它,但我在向量中有其他变量类型,它会工作得很好。这有什么问题?
【问题讨论】:
我有这个代码:
#include <iostream>
#include <vector>
using namespace std;
int main(){
vector <bool> v;
cin >> v[0];
return 0;
}
为什么我不能这样做?编译器不会编译它,但我在向量中有其他变量类型,它会工作得很好。这有什么问题?
【问题讨论】:
这是因为std::vector<bool> 是一种特化,根本不像一个向量。这被广泛认为是标准中的一个主要缺陷。
为了节省内存,vector<bool> 将每个元素存储为单个位。但是位不能单独寻址,因此operator[] 不能返回连接到位的bool& 引用。相反,它返回 vector<bool>::reference... 而 cin 不提供函数重载来处理这个问题。
(juanchopanza 正确地指出你的向量没有元素零。但即使它通过resize 或其他机制实现,operator[] 不返回引用的事实仍然会妨碍。 )
【讨论】:
std::vector<bool>的奇怪在这种情况下不是问题。
operator[] 分配是可以的,但是获取它返回的任何地址都行不通。
在您调用v[0] 时,向量的大小为零,因此您访问的范围越界。这是未定义的行为。
此外,std::vector<bool> 是一个具有奇怪行为的特化,因为它不包含单独的 bool 元素。它的operator[] 返回一种代理对象,对该运算符的调用可能不会达到您的预期。应该小心使用,或者根本不使用。
您可以通过将值读入局部变量然后将其推入向量的后面来解决该问题,如本工作示例 (similar live demo here) 所示:
#include <vector>
#include <iostream>
int main()
{
std::vector<bool> v;
std::cout << std::boolalpha;
v.push_back(true);
std::cout << v[0] << std::endl;
bool b;
cin >> b;
v[0] = b;
std::cout << v[0] << std::endl;
}
【讨论】:
v.resize(1) 被调用了。
std::vector<bool> 这么多年了,现在我不知道它在哪里坏了,在哪里不坏。
这应该可行:
#include <iomanip>
...
bool a;
cin >> boolalpha >> a;
v.push_back(a);
(除了 Ben Voigt 提到的问题之外,您当前的代码对于 bool 以外的类型是不安全的,因为当您访问 v[0] 时,您的向量是空的。)
【讨论】: