std::bitset使用疑问:声明后为何无法直接传入字符赋值?
关于std::bitset声明后赋值的问题解析
咱们先把你遇到的问题拆解开,一步步理清楚:
为什么第三种写法会报错?
你第三种写法里的foo(myString.c_str()[i]),是把已经声明好的bitset<8>对象foo当成函数来调用,但std::bitset根本没有定义这样的函数调用运算符(operator()),所以编译器才会抛出no match for call to ‘(std::bitset<8>) (const char&)’的错误——简单说就是,你用错了赋值的方式。
对比前两种写法:写法1和写法2都是在循环里临时构造一个新的bitset对象,然后直接输出这个临时对象;而第三种写法是想给已经存在的foo对象赋值,这是完全不同的操作,不能套用构造临时对象的语法。
bitset声明后到底能不能修改数据?
当然可以!只是你用错了修改的方式。std::bitset是固定大小的模板类(比如你声明的bitset<8>就是固定8位),它提供了多种修改数据的方式:
- 逐位修改:用
operator[],比如foo[0] = 1;可以设置第0位为1; - 整体赋值:直接赋值另一个
bitset对象,或者用from_ulong()、from_string()这类成员函数批量设置。
你想要的正确写法(预先声明foo,循环中更新)
其实不需要逐位拷贝那么繁琐,直接用赋值运算符把临时构造的bitset对象赋值给foo就行,代码非常简洁:
#include <iostream> #include <bitset> #include <string> using namespace std; int main() { string myString = "Hi"; bitset<8> foo; // 预先声明 for (int i = 0; i < myString.size(); ++i) { // 直接把临时构造的bitset赋值给foo foo = bitset<8>(myString[i]); cout << foo << endl; } return 0; }
或者如果你想更明确地用成员函数赋值,也可以这样写:
foo.reset(); // 先重置所有位为0 foo.from_ulong(static_cast<unsigned long>(myString[i])); // 用char的数值设置所有位
为什么你的繁琐写法能运行但冗余?
你写的逐位拷贝代码:
for (std::size_t i = 0; i < myString.size(); ++i) { bitset<8>bar(myString.c_str()[i]); foo[i] = bar[i]; }
其实逻辑上还有问题——你是把bar的第i位赋值给foo的第i位,但循环的i是字符串的索引(比如第一个字符对应i=0,第二个对应i=1),这时候只有foo[0]和foo[1]被赋值,剩下的位还是初始的0,根本不是你想要的“把整个字符转成8位二进制存到foo里”的效果。而直接赋值的方式可以一次性把字符对应的8位全部覆盖到foo里,才是正确的操作。
内容的提问来源于stack exchange,提问作者Lynob
相关产品推荐
相关产品推荐

