我在标准文档中找不到答案.C++语言标准是否要求sizeof(bool)
始终为1(1个字节),还是要定义此大小的实现?
正如(希望)我们都知道的那样,vector<bool>
完全被打破,不能被视为交流阵列.获得此功能的最佳方法是什么?到目前为止,我所想到的想法是:
vector<char>
替代,或vector<bool_wrapper>
你们怎么处理这个问题?我需要c_array()功能.
作为一个附带问题,如果我不需要c_array()方法,如果我需要随机访问,解决此问题的最佳方法是什么?我应该使用双端队列还是别的什么?
编辑:
c_array()
是专门的,所以每个bool需要1位.因此,您无法将其转换为C风格的数组.当然,由于可能的对齐问题,我必须读入my_bool :(
struct my_bool
{
bool the_bool;
};
vector<my_bool> haha_i_tricked_you;
Run Code Online (Sandbox Code Playgroud) 为什么这段代码有效
std::vector<int> intVector(10);
for(auto& i : intVector)
std::cout << i;
Run Code Online (Sandbox Code Playgroud)
这不是吗?
std::vector<bool> boolVector(10);
for(auto& i : boolVector)
std::cout << i;
Run Code Online (Sandbox Code Playgroud)
在后一种情况下,我收到一个错误
错误:从'std :: _ Bit_iterator :: reference {aka std :: _ Bit_reference}'类型的右值开始,无效初始化'std :: _ Bit_reference&'类型的非const引用
Run Code Online (Sandbox Code Playgroud)for(auto& i : boolVector)
它是众所周知的是std::vector<bool>
不符合标准的容器的需求,主要是因为打包表示防止T* x = &v[i]
从一个指针返回一个布尔值.
我的问题是:当reference_proxy重载address-of operator&
以返回pointer_proxy 时,这可以得到补救/缓解吗?
在大多数实现中,指针代理可以包含与reference_proxy相同的数据,即指向打包数据的指针和用于隔离指向的块内的特定位的掩码.然后,pointer_proxy的间接将产生reference_proxy.基本上两个代理都是"胖"指针,然而,与基于磁盘的代理容器相比,这些指针仍然相当轻.
而不是T* x = &v[0]
一个会然后做auto x = &v[0]
,并使用x
像if(*x)
没有问题.我也希望能够写作for(auto b: v) { /* ... */ }
问题:这种多代理方法是否适用于STL的算法?或者某些算法真的依赖于x
需要真实的需求bool*
?或者是否有太多连续的用户定义转换需要阻止它工作?在尝试完全完成上述实施草图之前,我想知道任何这样的障碍物.
更新(基于@HowardHinnant的回答和关于comp.std.c ++的古老讨论)
你可以在很大程度上模仿内置类型:对于任何给定的类型T,一对代理(例如reference_proxy和iterator_proxy)可以在reference_proxy :: operator&()和iterator_proxy :: operator*的意义上相互一致. ()是彼此相反的.
但是,在某些时候,需要将代理对象映射回来以表现为T*或T&.对于迭代器代理,可以重载operator - >()并访问模板T的接口,而无需重新实现所有功能.但是,对于参考代理,您需要重载operator.(),这在当前C++中是不允许的(尽管Sebastian Redl在BoostCon 2013上提出了这样的提议).您可以像引用代理中的.get()成员一样进行冗长的解决方法,或者在引用中实现所有T的接口(这是对vector :: bit_reference所做的),但这会丢失内置语法或引入用户定义的转换,这些转换没有用于类型转换的内置语义(每个参数最多只能有一个用户定义的转换).
我有以下代码片段,它接受std::vector<int> list
并在所有向量元素中写入零.这个例子工作得非常好.
#include <vector>
#include <iostream>
#include <algorithm>
int main () {
std::vector<int> list {1, 1, 2};
auto reset = [](int & element){element = 0;};
auto print = [](int element) {std::cout << element << " ";};
std::for_each(list.begin(), list.end(), reset);
std::for_each(list.begin(), list.end(), print);
}
Run Code Online (Sandbox Code Playgroud)
如果我把改变来自载体的种类int
来bool
,代码将无法编译.
#include <vector>
#include <iostream>
#include <algorithm>
int main () {
std::vector<bool> list {true, true, false};
auto reset = [](bool & element){element = false;};
auto print = [](int element) {std::cout << …
Run Code Online (Sandbox Code Playgroud) 我想vector
从一对vector
s 创建一对。例如,如果A
is std::vector A = [1 0 1]
和B
is std::vector B = [0 1 0]
,我想要一个std::vector C = [1 0, 0 1, 1 0]
where 的结构C_i = std::pair(A_i,B_i)
。
我会避免for
在两个向量之间循环,因此我正在寻找几行代码,例如std::transform()
。
我尝试了以下代码:
std::vector<bool> boolPredLabel(tsLabels.size());
std::vector<bool> boolRealLabel(tsLabels.size());
std::vector<std::pair<bool,bool>> TrPrPair(tsLabels.size());
std::transform(boolRealLabel.begin(), boolRealLabel.end(), boolPredLabel.begin(), TrPrPair.begin(),std::make_pair());
Run Code Online (Sandbox Code Playgroud)
这导致我出现编译器错误:
error: no matching function for call to ‘make_pair()’
std::transform(boolRealLabel.begin(), boolRealLabel.end(), boolPredLabel.begin(), TrPrPair.begin(),std::make_pair());
...
note: candidate expects 2 arguments, 0 provided
std::transform(boolRealLabel.begin(), boolRealLabel.end(), boolPredLabel.begin(), TrPrPair.begin(),std::make_pair()); …
Run Code Online (Sandbox Code Playgroud) 根据这个问题的答案,std::vector<bool>
实现“特殊”逻辑(允许每个布尔值存储在单个位中,而不是占用整个字节),因此,它并不能完全满足因此不鼓励使用 STL 容器及其使用。然而,出于向后兼容性的原因,保留了“特殊”逻辑。
我的问题是,如果 C++ 实现者抛弃“特殊”逻辑并变成模板std::vector<bool>
的另一种专门化std::vector
,这会导致什么向后兼容性问题?即旧软件可能依赖的某些特殊行为是否需要保留位打包实现?(我唯一能想到的是,RAM 受限环境中的一些旧软件可能依赖内存使用量减少八倍才能运行,但这在大多数情况下似乎是一个相对较小的问题)
试图使用std::vector<bool>
我有一个编译器错误,这对我来说非常令人惊讶.
简而言之,取一个元素的地址std::vector<unsigned char>
并将其赋值给unsigned char
指针:
std::vector<unsigned char> test(10);
unsigned char *pb = &test[0];
Run Code Online (Sandbox Code Playgroud)
效果非常好,同时尝试std::vector<bool>
使用编译器错误导致同样的事情:
int main() {
std::vector<bool> test(10);
bool *pb = &test[0]; // line 4, compile error
return 0;
}
Run Code Online (Sandbox Code Playgroud)
在Visual Studio上,它表示如下:
std::vector bool cannot convert std::_Vb_reference<_Alloc> * to bool *
Run Code Online (Sandbox Code Playgroud)
而codepad(参见http://codepad.org/vaiN3iEq上的例子)说:
cc1plus: warnings being treated as errors
In function 'int main()':
Line 4: warning: taking address of temporary
Line 4: error: cannot convert '__gnu_norm::_Bit_reference*' to 'bool*' in initialization
compilation …
Run Code Online (Sandbox Code Playgroud) 在C++代码的开头,我初始化一个1000000(百万)bool类型数据的向量.但是,在valgrind中,最大堆+堆栈使用量显示为200Kb.鉴于Bool是1字节,不应该是1 Mb?
有没有我没有意识到的优化?或者我错过了什么?
谢谢你的提前.
我使用的是Ubuntu64 16.04系统.编译没有-O
参数的代码.
编辑:代码可以简化为此,
vector<bool> * isPrime;
int main(){
isPrime = new vector<bool>(1000000, true);
}
Run Code Online (Sandbox Code Playgroud)
编辑2:似乎有一个我没有意识到的优化(在评论中说明).谢谢.
我正在创建自己的矩阵类。当谈到用于更改某个元素的值的“at”函数时,我有这个。
T & at(unsigned int raw, unsigned int col)
{
return (_matrix.at(index(raw, col)));
}
Run Code Online (Sandbox Code Playgroud)
知道
std::vector<T> _matrix;
Run Code Online (Sandbox Code Playgroud)
它适用于所有类型的布尔值。我无法执行此操作。
matrix.at(1, 1) = true;
Run Code Online (Sandbox Code Playgroud)
这很奇怪,因为我的实现与 std::vector "at" 函数相同,它适用于布尔值。
有任何想法吗 ?谢谢。