C++17下使用std::tie绑定bool位域成员出现取值异常问题
核心问题原因
- C++标准明确规定:位域成员无法直接绑定到左值引用。当你尝试将位域绑定到
const T&类型的引用时,编译器会隐式生成一个存储了位域值的临时对象,再将引用绑定到这个临时对象上。 std::tie的作用是生成存储参数左值引用的std::tuple,你将位域传入std::tie时,tuple中实际存储的是临时对象的引用,这个临时对象在tie函数调用结束后就会被销毁,返回的tuple就持有了悬垂引用,访问悬垂引用属于未定义行为,因此你读到的值不符合预期。- 你直接单独定义
const bool& ref_1 = default_bitmask.first;时,临时对象的生命周期会被延长到和引用变量ref_1一致,因此访问是合法的,表现符合预期。
修复方案
你只需要将tie函数修改为按值返回tuple即可,避免引用悬垂问题:
#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 ) { // 替换std::tie为std::make_tuple,按值存储位域的拷贝 return std::make_tuple( 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 ); // 正常通过 assert( std::get< 0 >( tie( default_bitmask ) ) == true ); // 正常通过 assert( std::get< 0 >( tie( custom_bitmask ) ) == false ); // 正常通过 }
补充说明:如果你希望通过tuple修改原结构体的位域成员是无法实现的,C++不支持指向位域的指针或可修改左值引用,因此按值返回tuple是满足比较需求的最优方案。
内容的提问来源于stack exchange,提问作者nyarlathotep108
相关产品推荐
相关产品推荐

