我在C++17中有以下代码,其中我定义了一个struct,它是位掩码,成员变量是bool类型的位字段。
我正在定义一个tie函数,这样我就可以将它转换成一个类似的std::tuple对象,这是很方便的。问题是:std::tie似乎做错了什么,即使默认构造函数正确地将其初始化为true,第一个成员变量的值似乎也是false。
手动获取bool对位字段的单个引用似乎如预期的那样工作。
我目前正在使用CLang 12。
这是代码:
#include <cassert>
#include <tuple>
struct Bitmask
{
Bitmask( )
: first{true}
, second{false}
, third{false}
{
}
bool first : 1;
bool second : 1;
bool third : 1;
};
auto
tie( const Bitmask& self )
{
return std::tie( self.first, self.second, self.third );
}
int main()
{
Bitmask default_bitmask;
Bitmask custom_bitmask;
custom_bitmask.first = false;
custom_bitmask.second = true;
const bool& ref_1 = default_bitmask.first;
const bool& ref_2 = custom_bitmask.first;
assert( ref_1 != ref_2 ); // this check works
assert( std::get< 0 >( tie( default_bitmask ) ) == true ); // this check fails
assert( std::get< 0 >( tie( custom_bitmask ) ) == false ); // this check works
}发布于 2021-05-07 15:10:15
不可能有指向位字段的引用或指针。来自优先选择:
因为位字段不一定从字节的开头开始,所以不能接受位字段的地址。对位字段的指针和非const引用是不可能的。当从位字段初始化const引用时,会创建一个临时的(其类型是位字段的类型),复制使用位字段的值初始化,并将引用绑定到该临时字段。
来自标准:
运算符
&的地址不应应用于位字段,因此没有指向位字段的指针。非连接引用不应绑定到位字段(dcl.init.ref).
附注:
[注3:如果
const T&类型的引用的初始化器是引用位字段的lvalue,则引用绑定到临时初始化的位字段值;引用不直接绑定到位字段。见dcl.init.ref。-尾注]
这样编译的唯一原因是tie将Bitmask类型作为const。它的每个位字段成员被视为const,std::tie返回一个const引用的std::tuple。正如上面引用的段落所述,这些引用指的是数据成员的副本,而不是那些实际的数据成员。然后,就像您试图通过引用返回一个const int & x = 10;一样,您最终得到了一个悬空引用的元组。最后,试图获取引用对象的值会导致未定义的行为。
https://stackoverflow.com/questions/67437232
复制相似问题